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 шт):

Автор решения: MBo

При вызове функции 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)

→ Ссылка