Из системной очереди сообщения распределяются по приложениям. Для каждого приложения Windows организует отдельную очередь сообщений прикладной программы, которая по умолчанию вмещает до 8 сообщений. В процессе распределения сообщений по приложениям Windows извлекает очередное сообщение из системной очереди, определяет, с каким окном оно связано, и помещает в очередь того приложения, которому принадлежит окно.
Обработку прикладной очереди сообщений осуществляет уже само приложение. Для этого программа организует так называемый цикл обработки сообщений. В нем осуществляется выбор нового сообщения из очереди прикладной программы и вызов диспетчера для его обработки оконной функцией.
Для извлечения сообщений из очереди приложения существуют функция:
BOOL PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg );LpMsg – возвращаемое программе сообщение. Оно имеет следующую структуру
typedef struct tagMSG { HWND hwnd; // окно, для которого предназначено сообщение UINT message; // собственно сообщение WPARAM wParam; // дополнительная информация LPARAM lParam; // к сообщению DWORD time; // время посылки сообщения POINT pt; // положение курсора мыши} MSG, *PMSG;В поле hwnd структуры MSG записывается дескриптор окна, которому адресовано сообщение; тип сообщения записывается в 32-разрядное поле message, а дополнительная информация (параметры сообщения) – в поля wParam и lParam. Типы WPARAM и LPARAM определены при помощи typedef соответственно как UINT и LONG.
|
|
hWnd – дескриптор окна, для которого ожидается сообщение (передача в этом параметре нуля указывает на то, что извлекается сообщение, предназначенное любому окну прикладной программы).
wMsgFilterMin, wMsgFilterMax – минимальное и максимальное допустимые значения поля message в записи Msg (для получения всех сообщений оба параметра нужно установить в нуль).
wRemoveMsg – режим работы функции PeekMessage: pm_NoRemove – принятое сообщение остается в очереди, pm_Remove – сообщение удаляется из очереди. Флаг pm_NoYield используется в комбинации с одним из этих значений, чтобы предотвратить передачу управления другим задачам.
Функция GetMessage является частным случаем PeekMessage. В ней отсутствует параметр wRemoveMsg, она всегда удаляет сообщения из очереди и возвращает True, если принятое сообщение не является сообщением wm_Quit.
Сообщения, поступающие от клавиатуры, требуют дополнительной обработки – трансляции. Поэтому после приема сообщения нужно вызвать функцию
BOOL TranslateMessage(CONST MSG* lpMsg // информация сообщения );Она преобразовывает сообщение о нажатии клавиши в сообщение о приходе символа. Дело в том, что сообщения, генерируемые драйвером клавиатуры, содержат виртуальный key-code, который определяет, какая клавиша была нажата, но не определяет символьное значение этой клавиши. Функция TranslateMessage, не изменяя переданное ей сообщение, помещает еще одно сообщение с соответствующим символьным значением в очередь приложения. Функция возвращает True, если переданное ей сообщение оказалось клавиатурным.
|
|
После трансляции сообщение диспетчиризируется оконной процедуре:
LRESULT DispatchMessage(CONST MSG* lpmsg // информация сообщения );Результат обработки сообщения возвращается как значение функции. Его смысл зависит от типа обработанного сообщения и чаще всего игнорируется прикладной программой.