Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WinAPI.docx
Скачиваний:
49
Добавлен:
16.12.2018
Размер:
3.43 Mб
Скачать

2.3.2 Синхронные и асинхронные сообщения

Ранее было рассказано о передаче окну сообщений, что означает вызов операционной системой Windows оконной процедуры. Но в программах для Windows имеется цикл обработки сообщений, который берет сообщения из очереди сообщений, вызывая функцию GetMessage, и отправляет их оконной процедуре, вызывая функцию DispatchMessage.

Так что же, буферизуются ли сообщения для Windows-программы (так же как в обычной программе буферизуется ввод с клавиатуры) и затем пересылаются дальше, или она (программа для Windows) получает сообщения непосредственно снаружи? И так, и этак.

Одни и те же сообщения могут быть и "синхронные" (queued), и "асинхронные" (nonqueued). Синхронными сообщениями называются сообщения, которые Windows помещает в очередь сообщений программы, и которые извлекаются и диспетчеризуются в цикле обработки сообщений. Асинхронные сообщения передаются непосредственно окну, когда Windows вызывает оконную процедуру. В результате оконная процедура получает все предназначенные для окна сообщения, как синхронные, так и асинхронные. Структура программ для Windows очень проста, поскольку у них имеется только одно центральное место обработки сообщений. Говорят, что синхронные сообщения помещаются в очередь сообщений (post), а асинхронные посылаются прямо в оконную процедуру (send).

Синхронными становятся сообщения, в основном, тогда, когда они являются результатом пользовательского ввода путем нажатия клавиш (например, WM_KEYDOWN и WM_KEYUP), это символы, введенные с клавиатуры (WM_CHAR), результат движения мыши (WM_MOUSEMOVE) и щелчков кнопки мыши (WM_LBOTTONDOWN).

Кроме этого синхронные сообщения включают в себя сообщение от таймера (WM_TIMER), сообщение о необходимости плановой перерисовки (WM_PAINT) и сообщение о выходе из программы (WM_QUIT).

Сообщения становятся асинхронными во всех остальных случаях. Часто асинхронные сообщения являются результатом синхронных. При передаче асинхронного сообщения в DefWindowProc из оконной процедуры, Windows часто обрабатывает сообщение, отправляя оконной процедуре другие асинхронные сообщения.

Очевидно, что процесс этот сложен, но к счастью большая часть сложностей ложится на Windows, а не на наши программы. С позиции оконной процедуры, эти сообщения проходят через нее упорядочено или синхронно.

Оконная процедура может что-то сделать с этими сообщениями, а может и проигнорировать их. По этой причине оконную процедуру назвали "конечным пунктом обработки" (ultimate hook). Сообщения извещают оконную процедуру почти обо всем, что влияет на окно.

Часто асинхронные сообщения являются результатом вызова определенных функций Windows или непосредственным результатом вызова функции SendMessage. (Кроме этого, сообщения могут помещаться в очередь сообщений посредством вызова функции PostMessage.)

Например, когда WinMain вызывает функцию CreateWindow, Windows создает окно и для этого отправляет оконной процедуре асинхронное сообщение WM_CREATE. Когда WinMain вызывает ShowWindow, Windows отправляет оконной процедуре асинхронные сообщения WM_SIZE и WM_SHOWWINDOW. Когда WinMain вызывает UpdateWindow, Windows отправляет оконной процедуре асинхронное сообщение WM_PAINT.

Сообщения не похожи на аппаратные прерывания. Во время обработки в оконной процедуре одного сообщения программа не может быть прервана другим сообщением. Только в том случае, если оконная процедура вызвала функцию, которая сама стала источником нового сообщения, то оконная процедура начнет обрабатывать это новое сообщение еще до того, как функция вернет управление программе.

Цикл обработки сообщений и оконная процедура работают не параллельно. Когда оконная процедура обрабатывает сообщение, то это результат вызова функции DispatchMessage в WinMain. DispatchMessage не завершается до тех пор, пока оконная процедура не обработала сообщение.

Но заметьте, что оконная процедура должна быть повторно-входимой (reentrant). Это означает, что Windows часто вызывает WndProc с новым сообщением, как результат вызова функции DefWindowProc в WndProc с предыдущим сообщением. В большинстве случаев повторная входимость оконной процедуры не создает проблем, но об этом следует знать.

Например, предположим, что вы вводите переменную в процесс обработки сообщения оконной процедурой и затем вызываете функцию Windows. Можете ли вы быть уверены в том, что после возврата функцией своего значения, ваша переменная осталась той же самой? Конечно, нет — в том случае, если конкретная функция Windows, которую вы вызвали, стала источником другого сообщения, и оконная процедура изменила вашу переменную при обработке этого второго сообщения. Это одна из причин того, что при компиляции программ для Windows необходимо отключать некоторые возможности оптимизации.

Часто возникает необходимость того, чтобы оконная процедура сохраняла информацию, полученную в сообщении, и использовала ее при обработке другого сообщения. Тогда эту информацию следует описывать в оконной процедуре в виде статических переменных, либо хранить в глобальных переменных.

Все вышеизложенное станет более понятным, когда вы прочитаете в следующих главах об оконных процедурах, способных обрабатывать большое число сообщений.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]