WinApi. Обработка результата функции GetWindowLong
Начал изучать основу WinAPI (ну как начал, задание от препода по универу). Задание. Необходимо сделать так, чтобы условие ниже заработало, если заменить оператор "&" на "==".
// Функция обработки сообщений
...
...
case WM_LBUTTONDBLCLK: {
if (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP) {...}
Из ответов авторов на мой вопрос, понял, что функция GetWindowLong возвращает 32-битное слово, где биты являются флагами. Что значит необходимо при использовании оператора "==" вместо "&", обработать GetWindowLong так, чтобы остался только необходимый мне бит. Как это сделать (если поставлены флаги: WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_THICKFRAME | WS_VISIBLE | WS_SYSMENU)? Заранее благодарю за выделенное время. Уточнения. Код сам по себе рабочий, однако задание по замене оператора "&" на "==", это прикол от преподавателя, которое нужно сделать.
Ответы (1 шт):
При вызове функции GetWindowLong с параметром GWL_STYLE вы получаете результат - 32-битное слово, биты которого являются флагами, показывающими, с каким стилем было создано данное окно. Если при его создании (CreateWindow) был указан флаг WS_POPUP (0x800000000L), то и в результате будет установлен самый старший бит.
Чтобы проверить этот бит, накладывается соответствующая маска с помощью побитового AND.
В данном конкретном случае ( только для этого флага) можно проверить, что число отрицательное.
Можно выполнить сдвиг вправо и проверить, что результат равен -1
(GetWindowLong(hWnd, GWL_STYLE) >> 31) == -1
Это обусловлено тем, что для знакового числа выполняется арифметический сдвиг, при котором знаковый бит заполняет освободившееся место, и при наличии флага WS_POPUP получится 0xFFFFFFFF==-1
Но всё это - обработка результата GetWindowLong (как и с AND), без обработки не получится сравнить на равенство, потому что в нём установлено ещё несколько флагов. Разве что вы точно знаете весь набор флагов, раз сами создаёте окно...
Добавлю ещё один момент, который нужно знать. Конструкция
if (GetWindowLong(hWnd, GWL_STYLE) & WS_POPUP) {...}
не совсем корректная. Например, если проверить таким образом флаг
if (GetWindowLong(hWnd, GWL_STYLE) & WS_OVERLAPPED) {...}
то можно получить отрицательный результат, и это при том, что окно было создано перекрывающимся. Правильно:
if ((GetWindowLong(hWnd, GWL_STYLE) & WS_OVERLAPPED) == WS_OVERLAPPED) {...}
(дело в значении флага WS_OVERLAPPED 0x00000000L
)