Система сообщенийНА ЭТОЙ СТРАНИЦЕ:О сообщениях и очередях сообщений Оконные сообщения Типы сообщений: - Системные сообщения - Сообщения, определяемые приложением Маршрутизация сообщений: - Асинхронные сообщения - Синхронные сообщения Манипулирование сообщениями: - Цикл сообщений - Оконная процедура - Фильтрация сообщений Помещение сообщений в очередь и передача их напрямую оконной процедуре: - Добавление сообщений в очередь - Передача сообщения напрямую оконной процедуре - Широковещательные сообщения - Тупиковые ситуации - Сообщение-запрос Функции для работы с сообщениями Структуры для работы с сообщениями Сообщения используемые при работе с сообщениями Примеры О сообщениях и очередях сообщений(о приложениях управляемых событиями)В отличие от приложений для MS-DOS, приложения для Windows управляются событиями. В таких приложениях нет возможности вызывать функцию для получения ввода. Вместо этого эти приложения дожидаются, чтобы система самостоятельно передавала им входящую информацию. Вводимые данные направляются системой для каждого окна отдельно. В этих целях каждое окно связано с функцией называемой ОКОННОЙ ПРОЦЕДУРОЙ. Если для какого-либо из окон есть какая-то входящая информация, то система запускает (вызывает) соответствующую оконную процедуру, передавая ей введенную информацию. Оконная процедура должна обработать полученную информацию и вернуть управление обратно системе. Оконные сообщенияСистема отправляет входящие данные оконной процедуре в виде СООБЩЕНИЙ. Эти сообщения могут генерироваться, как и системой, так и самими приложениями. Система генерирует сообщение при каждом событии ввода, например при наборе текста пользователем на клавиатуре, перемещении мыши или щелчке клавишей мыши по элементу управления (например, полосе прокрутки). Так же система генерирует сообщения как реакцию на происходящие в ней изменения, касающиеся приложения, таких как смена системного шрифта или изменения размеров одного из окон приложения. Приложение может генерировать сообщения для своих окон или для передачи данных окнам других приложений. Система передает сообщение оконной процедуре в виде набора из четырех параметров: описатель окна, идентификатор сообщения и двух значений называемых ПАРАМЕТРАМИ СООБЩЕНИЯ. Описатель окна используется для определения, какому из окон приложения предназначается сообщение, и система по нему определяет нужную оконную процедуру. Идентификатор сообщения это символическая константа, которая определяет назначение сообщения. Оконная процедура использует его для определения того, как обработать поступившее сообщение. Например, идентификатор сообщения WM_PAINT, говорит оконной процедуре, что клиентская область ее окна была изменена и требует перерисовки. Параметры сообщения содержат данные или указатели на данные, которые могут понадобиться оконной процедуре для обработки поступившего сообщения. Эти значения и их смысл зависят от конкретного сообщения. Если в сообщении не используются параметры, то они обычно устанавливаются в NULL. Оконная процедура должна проверять идентификатор сообщения, для того чтобы определить, что ей делать с параметрами сообщения. ТИПЫ СООБЩЕНИЙСистемные сообщенияСистема высылает системные сообщения для установки связи с приложением. Эти сообщения используются для контроля над приложением, предоставления ему входящих данных и другой информации. Приложение, в свою очередь, тоже может генерировать системные сообщения. В основном приложения используют эти сообщения для управления окнами, созданных на основе предопределенных классов. Каждое системное сообщение имеет уникальный идентификатор и соответствующую ему символическую константу, которые определяют назначение сообщения. Например, символическая константа WM_PAINT является просьбой на перерисовку содержимого окна. Префикс символической константы указывает на категорию, к которой принадлежит сообщение. Например: Основные оконные сообщения покрывают собой широкий диапазон необходимой для работы приложения информации и различных запросов, включая ввод с мыши и клавиатуры, ввод из меню и диалогового окна, управление окном и динамическим обменом данных (DDE). Сообщения, определяемые приложениемПриложение может создавать свои сообщения для работы со своими окнами или для установки связи с окнами других процессов. Используются следующие идентификаторы сообщений: Маршрутизация сообщенийСистема использует два пути, для того чтобы доставить сообщение оконной процедуре: Асинхронные сообщенияСистема может в один и тот же момент времени отображать любое количество окон. При перемещении мыши над каким-либо окном или вводе данных в это окно с клавиатуры система использует очередь сообщений. Система управляет одной системной очередью и одной из очередей сообщений GUI потоков. Для того чтобы не тратить время на создание очередей сообщений для не GUI потоков, все потоки изначально создаются без очередей сообщений (т. е. при создании нового потока, система предполагает, что он не будет иметь отношения к поддержке пользовательского интерфейса). Очередь сообщений потока создается только при первом вызове потоком какой-либо пользовательской или GDI функции. Если процесс создает три потока и все эти потоки вызывают, например функцию CreateWindow, то и очередей сообщений потоков тоже будет три. Каждый раз, когда пользователь перемещает мышь, нажимает кнопки мыши или набирает текст на клавиатуре, драйвер мыши или клавиатуры преобразует этот ввод в сообщения и размещает их в системной очереди сообщений. Система, удаляя сообщение из системной очереди, проверяет какому окну предназначено сообщение и, затем, перемещает его в очередь сообщений потока, который создал указанное в сообщении окно. Поток, удаляя сообщение из своей очереди, просит систему передать его соответствующей оконной процедуре для обработки. Асинхронное сообщение помещается в очередь сообщений путем заполнения структуры MSG. В нее записывается описатель окна, которому предназначается сообщение, идентификатор этого сообщения, два его параметра, время появления сообщения и позицию курсора мыши. Поток может поместить сообщение в свою очередь сообщений, или очередь другого потока, используя функцию PostMessage или PostThreadMessage. При проверки сообщений приложение может удалить сообщение из своей очереди сообщений используя функцию GetMessage. Проверка сообщения без его удаления из очереди сообщений осуществляется функцией PeekMessage. После удаления сообщения из своей очереди приложение может использовать функцию DispatchMessage, которая заставляет систему передать сообщение нужной оконной процедуре для его обработки. Этой функции необходимо передать указатель на структуру MSG, которая была заполнена до этого функцией GetMessage или PeekMessage. DispatchMessage передает оконной процедуре описатель окна, идентификатор сообщения и оба его параметра, но не передает время его появления и позицию курсора на экране в этот момент. Приложение может получить эту информацию вызовом функций GetMessageTime и GetMessagePos во время обработки сообщения. Поток может использовать функцию WaitMessage, для того, чтобы передать управление другим потокам, пока в его очереди сообщений нет никаких сообщений. Эта функция останавливает работу потока и не возобновляет ее до появления нового сообщения в очереди сообщений потока. Синхронные сообщенияСинхронные сообщения передаются напрямую оконной процедуре в обход системной очереди и очереди сообщений потока. Обычно эти сообщения высылаются окну для его уведомления о событиях происходящих с ним. Например, когда пользователь активирует новое окно приложения, ему высылается серия из трех сообщений: WM_ACTIVATE, WM_SETFOCUS и WM_SETCURSOR. Эти сообщения уведомляют окно, что оно было активировано, ввод с клавиатуры направляется в него, а курсор находится в его пределах. Так же эти сообщения могут быть результатом вызова некоторых системных функций. Например, сообщение WM_WINDOWPOSCHANGED высылается после использования приложением функции SetWindowPos для перемещения окна по экрану. Манипулирование сообщениямиПриложение должно обрабатывать и удалять все сообщения в очередях своих потоков. Однопоточное приложение обычно использует цикл обработки сообщений, который располагают в функции WinMain. В многопоточных приложениях такие циклы располагают в каждом потоке, который создает окна. Цикл сообщенийПростейший цикл сообщений состоит из трех функций: GetMessage, TranslateMessage и DispatchMessage. Заметим, что в случае появления какой-либо ошибки функция GetMessage возвращает -1. В этом случае необходима специальная обработка этой ситуации. Пример цикла сообщений:
MSG msg; Функция GetMessage извлекает сообщение из очереди и копирует его в структуру типа MSG. Эта функция возвращает ненулевое значение, но при извлечении сообщения WM_QUIT она возвращает ЛОЖЬ и цикл завершает свою работу. В однопоточных приложениях завершение работы цикла сообщений часто является первым шагом к закрытию этого приложения. Приложение может самостоятельно вызвать завершение этого цикла функцией PostQuitMessage. Она обычно является реакцией на сообщение WM_DESTROY в оконной процедуре главного окна приложения. Если вы укажете описатель окна во втором параметре функции GetMessage, то функция будет извлекать из очереди сообщения, предназначенные только указанному окну. Если поток получает ввод с клавиатуры, то цикл сообщений должен иметь функцию TranslateMessage. Система генерирует сообщения виртуальных клавиш (WM_KEYDOWN и WM_KEYUP) при каждом нажатие клавиши пользователем. Сообщение виртуальной клавиши содержит код виртуальной клавиши, который показывает какая, была нажата клавиша (а не ее символьное значение). Функция TranslateMessage переводит сообщение виртуальной клавиши в символьное сообщение (WM_CHAR) и помещает его обратно в очередь сообщений приложения. Это символьное сообщение будет извлечено на следующей итерации цикла сообщения и передано оконной процедуре. Функция DispatchMessage отсылает сообщение оконной процедуре ассоциированной с описателем окна указанном в структуре MSG. Если описателем окна является HWND_TOPMOST, то функция отправляет сообщение оконным процедурам всех окон верхнего уровня в системе. Если описатель окна установлен в NULL, то функция никуда не отсылает такое сообщение. Цикл сообщений главного потока приложения располагается после инициализационной части и создания хотя бы одного окна. Начав выполняться, цикл сообщений продолжает извлекать сообщения из очереди сообщений потока и отправлять их в соответствующие окна. Цикл сообщений завершает свою работу при извлечении функцией GetMessage сообщения WM_QUIT. Вы можете изменить цикл сообщений несколькими способами. Например, вы можете извлекать сообщения из очереди без передачи их оконной процедуре. Это используется, если необходимо передавать сообщения другому окну, а не тому, чей описатель указан в сообщении. Также функция GetMessage может извлекать из очереди только определенные сообщения. Это позволяет обойти очередность FIFO расположения сообщений в очереди. Приложение, использующее акселераторные клавиши должно переводить клавиатурные сообщения в командные. Для этого цикл сообщения должен содержать вызов функции TranslateAccelerator. Если поток использует немодальное диалоговое окно, цикл сообщений должен содержать функцию IsDialogMessage, которая позволяет диалоговому окну получать ввод с клавиатуры. Оконная процедураОконная процедура это функция, которая получает и обрабатывает все сообщения адресованные ее окнам. Каждый оконный класс имеет оконную процедуру и каждое окно, созданное на основе такого класса, использует эту процедуру для реагирования на предназначенные для них сообщения. Система передает сообщение оконной процедуре путем инициализации ее параметров. Оконная процедура, для того чтобы выполнить соответствующее сообщению действие, проверяет идентификатор сообщение и в процессе выполнения этих действий использует информацию из параметров сообщения. Если оконная процедура не должна обрабатывать некоторые сообщения, то такие сообщения должны возвращаться оконной процедурой обратно в систему для их обработки по умолчанию. Для этого оконная процедура должна использовать функцию DefWindowProc, которая обрабатывает сообщение по умолчанию и возвращает результат этой обработки. Оконная процедура должна вернуть это значение при своем завершении как результат своих действий над полученным ею сообщением. Большинство оконных процедур обрабатывает только несколько сообщений а остальные отдает системе вызовом функции DefWindowProc. Так как все окна одного оконного класса используют одну и туже оконную процедуру, то ей приходиться отвечать на сообщения различных окон. Для того чтобы оконная процедура отличала сообщения для разных окон, она должна проверять описатели окон поступающих сообщений. Фильтрация сообщенийПриложение может выбирать определенные сообщения для извлечения из очереди (игнорируя при этом другие сообщения) указав фильтр сообщений в функции GetMessage или PeekMessage. Фильтр - это диапазон допустимых идентификаторов сообщений (указывается первый и последний идентификаторы), оконных описателей или и того и другого. Константы WM_KEYFIRST и WM_KEYLAST могут быть использованы для извлечения всех сообщений клавиатуры. Константы WM_MOUSEFIRST и WM_MOUSELAST могут быть использованы для извлечения всех сообщений мыши. При использовании фильтра убедитесь, что нужные для извлечения сообщения будут появляться в очереди в течение работы приложения. Например, если приложение извлекает из очереди только сообщения WM_CHAR, а ввода с клавиатуры не происходит, то функция GetMessage не вернет управления, что приведет к "зависанию" приложения. Помещение сообщений в очередь
|
Главная СООБЩЕНИЯ Ресурсы |