КАТЕГОРИИ:
АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника
|
Цикл приема сообщенийСообщение проходит в ОС путь от источника, создавшего это сообщение, до приемника, обрабатывающего его. Описание этого пути удобнее начать с конца. Приемником сообщения является обычно окно одного из приложений Windows. В ранних версиях Windows с каждым окном связывалась очередь сообщений, адресованных этому окну. Сейчас очередь сообщений связана с каждой нитью процесса приложения. Большинство сообщений по-прежнему посылаются из очереди одному из окон, принадлежащих данной нити, однако нить имеет возможность обработать сообщение, не пересылая его окну. В значительной части приложений либо имеется единственная нить, либо только одна из нитей создает окна и отвечает за обработку сообщений для окон. Работа нити процесса, владеющей окнами, основана на цикле приема сообщений, который начинает работу после инициализации (создания окон, присвоения начальных значений и т.п.) и продолжается до завершения работы нити. При использовании современных систем программирования (Delphi, Visual Studio и т.п.) цикл приема сообщений может оказаться скрытым от пользователя в теле методов системных классов, однако он, тем не менее, существует. Примерная структура цикла приема сообщений выглядит так:
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 завершает свое выполнение, но не выбирает сообщение из очереди.
|