Сообщения и их обработка
Посылка сообщений
Мы это сделаем на примере нажатия на клавишу. Когда вы нажимаете на клавишу, генерируется аппаратное прерывание. Клавиатурный драйвер Windows обрабатывает это прерывание и помещает соответствующее сообщение в общую очередь сообщений Windows.
При этом указывается, какое окно должно получить это сообщение. Затем Windows извлекает из своей очереди это сообщение и помещает его в очередь сообщений приложения, содержащего окно–адресат. Вслед за этим уже само приложение выбирает из очереди поступившее сообщение и передает его соответствующей оконной функции.
Этот процесс называется посылкой (post) сообщений, так как посылка сообщения напоминает посылку письма: посылающий сообщение указывает адресата, отправляет сообщение и больше о нем не беспокоится. Отправитель не знает, когда точно его сообщение получит адресат. Процесс посылки может показаться излишне сложным, однако для этого существует несколько причин:
Во–первых, аппаратные прерывания надо обрабатывать со всей возможной скоростью. Поэтому при приеме аппаратного прерывания драйвер не тратит время на передачу сообщения в очередь приложения, а ставит его в очередь сообщений Windows. Аппаратные прерывания являются асинхронными по отношению к выполняющемуся приложению, а обработка сообщений обязательно должна быть синхронной. Поэтому механизм посылки сообщений нельзя смешивать с аппаратными прерываниями.
А во–вторых, накопление событий в очереди приложения помогает уменьшить количество переключений между приложениями, так как Windows обычно дает приложению полностью обработать события из его очереди и лишь после этого переключается на другие приложения. Кроме того, некоторые события могут группироваться в одно во время нахождения в очереди.
Рисунок 1 Маршрутизация сообщений в Windows 3.x
Извлечение сообщений из очереди приложения и направление их соответствующим окнам осуществляет функция WinMain. Этот процесс выполняется в несколько приемов:
сообщение выбирается из очереди с помощью функции GetMessage или PeekMessage
затем сообщение транслируется с помощью функции TranslateMessage[0] (одно сообщение может порождать последовательность других или заменяться, как, например, происходит для сообщений клавиатуры WM_KEYDOWN). Часто трансляция состоит из вызова более чем одной функции, сюда могут добавляться специальные средства трансляции акселераторов и немодальных диалогов (об этом позже).
И только после этого оно направляется окну с помощью функции DispatchMessage (это называется диспетчеризацией)
Для выполнения этих операций существуют специальные функции. Эти функции образуют цикл обработки сообщений, так как после завершения обработки одного сообщения приложение должно приготовиться к обработке следующего. Цикл заканчивается только при завершении работы приложения.
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessage(&msg);}
Это самый простой вид цикла обработки сообщений. В реальных приложениях он более сложный. Все три функции, вызываемые здесь, принадлежат Windows. Назначение их должно быть понятно. Требуется добавить несколько замечаний о функции GetMessage. Эта функция имеет следующие аргументы:
BOOL GetMessage(lpMsg, hWnd, uMsgFilterMin, uMsgFilterMax);
lpMsg указывает на структуру MSG, в которую будет записано полученное сообщение. ............