- •«Исследование обмена сообщениями в Windows»
- •Механизм сообщений в Windows
- •Типы сообщений
- •Цикл приема сообщений
- •Оконные функции
- •Структура очереди сообщений
- •Асинхронная посылка сообщений
- •Синхронная посылка сообщений
- •Выполнение лабораторной работы
- •Пример выполнения задания
- •Варианты заданий
- •Контрольные вопросы
Цикл приема сообщений
Сообщение проходит в ОС путь от источника, создавшего это сообщение, до приемника, обрабатывающего его. Описание этого пути удобнее начать с конца.
Приемником сообщения является обычно окно одного из приложений Windows. В ранних версияхWindowsс каждым окном связываласьочередь сообщений, адресованных этому окну. Сейчас очередь сообщений связана с каждой нитью процесса приложения. Большинство сообщений по-прежнему посылаются из очереди одному из окон, принадлежащих данной нити, однако нить имеет возможность обработать сообщение, не пересылая его окну. В значительной части приложений либо имеется единственная нить, либо только одна из нитей создает окна и отвечает за обработку сообщений для окон.
Работа нити процесса, владеющей окнами, основана на цикле приема сообщений, который начинает работу после инициализации (создания окон, присвоения начальных значений и т.п.) и продолжается до завершения работы нити. При использовании современных систем программирования (Delphi,VisualC++ и т.п.) цикл приема сообщений может оказаться скрытым от пользователя в теле методов системных классов, однако он тем не менее существует.
Примерная структура цикла приема сообщений выглядит так:
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Первый параметр функции GetMessageсодержит адрес структуры, куда будет приниматься сообщение. Второй параметр содержит хэндл окна, чьи сообщения будут выбираться из очереди. ЗначениеNULLозначает все окна данной нити. Третий и четвертый параметры – нижняя и верхняя границы идентификаторов принимаемых сообщений. Пара значений0,0означает все сообщения. Функция возвращает0в единственном случае: если принято сообщениеWM_QUIT, которое означает завершение нити. Если в очереди нет требуемых сообщений, функция ожидает их появления. В это время могут работать другие процессы и нити.
Вместо GetMessageможет также использоваться функцияPeekMessage, основное отличие которой заключается в том, что она позволяет только проверить наличие сообщений, не выполняя ожидание в случае их отсутствия. Кроме того, пользователь может выбирать, следует ли при выполненииPeekMessageизымать сообщение из очереди или нужно пока оставить его в очереди. Эти возможности позволяют нестандартным образом строить цикл приема сообщений, достигая в некоторых случаях большей гибкости программы.
Функции GetMessageиPeekMessageне дают информации о времени посылки сообщения и о координатах курсора. Если эти данные нужны для правильной обработки сообщения, приложение может вызвать функцииGetMessageTimeиGetMessagePos.
Функция TranslateMessageнеобходима для программ, обрабатывающих клавиатурные сообщения о введенном символеWM_CHARиWM_SYSCHAR.Как было сказано выше, эти сообщения помещаются в очередь на основании анализа сообщений о нажатии/отпускании клавиш.
Функция DispatchMessage(msg)выясняет, какому из окон данной нити адресовано сообщение, вызываетоконную функциюданного окна для обработки сообщения и передает в нее структуру сообщенияmsg. После того, как оконная функция обработает сообщение, цикл приема сообщений продолжает свою работу.
В цикл приема сообщений могут входить дополнительные операторы, выявляющие сообщения, адресованные не окну, а самой нити (сообщения с хэндлом окна, равным NULL), и выполняющие обработку таких сообщений без вызоваDispatchMessage.
Еще одной функцией, которая может использоваться в нестандартном цикле приема сообщений, является WaitMessage. Эта функция просто проверяет, имеется ли в очереди к данной нити какое-либо сообщение, которое могла бы принять функцияGetMessage. Если нет, то работа нити блокируется, как и при выполненииGetMessage. Если сообщение имеется, тоWaitMessageзавершает свое выполнение, но не выбирает сообщение из очереди.