Существует также ряд функций, которые могут обрабатывать сообщения без участия DispatchMessage
и оконной процедуры. Если эти функции распознают сообщение, извлеченное из очереди, как "свое", они сами выполняют все необходимые действия по его обработке, и тогда TranslateMessage
и DispatchMessage
вызывать не нужно. К этим функциям, в частности, относятся следующие:
□ TranslateAccelerator
— на основе загруженной из ресурсов таблицы распознает нажатие "горячих" клавиш меню и вызывает оконную процедуру, передавая ей сообщение WM_COMMAND
или WM_SYSCOMMAND
, аналогичное тому, которое посылается при выборе соответствующего пункта меню пользователем;
□ TranslateMDISysAccel
— аналог предыдущей функции за исключением того, что распознает "горячие" клавиши системного меню MDI-окон;
□ IsDialogMessage
— распознает сообщения, имеющие особый смысл для диалоговых окон (например, нажатие клавиши CreateDialogXXXX
), но требующими аналогичной функциональности.
Перечисленные функции при необходимости вставляются в петлю сообщений. Листинг 1.6 показывает, как будет выглядеть петля сообщений, содержащая вызов TranslateAccelerator
для родительской MDI-формы и TranslateMDISysAccel
для дочерней.
while GetMessage(Msg, 0, 0, 0) do
if not TranslateMDISysAccel(ActiveMDIChildHandle, Msg)
and not TranslateAccelerator(MDIFormHandle, AccHandle, Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
При отправке сообщения, в отличие от посылки, оно не ставится в очередь, а передается оконной процедуре напрямую. Отправить сообщение можно, например, с помощью функции SendMessage
. Если эта функция вызывается из той же нити, которой принадлежит окно-адресат, то фактически это эквивалентно прямому вызову оконной процедуры. Если окно принадлежит другой нити, данное сообщение становится в отдельную очередь, имеющую более высокий приоритет, чем очередь для посланных сообщений. Функции GetMessage
и PeekMessage
сначала выбирают все сообщения из этой очереди и отправляют их на обработку, и лишь затем приступают к анализу очереди посланных сообщений.
Поскольку сообщения, отправленные окну, передаются оконной процедуре напрямую либо диспетчеризуются внутри GetMessage
или PeekMessage
, то эти сообщения не попадают в функции TranslateMDISysAccel
, TranslateAccelerator
и TranslateMessage
. Это необходимо учитывать при передаче окну сообщений, эмулирующих нажатие клавиш на клавиатуре. Такие сообщения окну нужно посылать, а не отправлять, чтобы они прошли полный цикл обработки и окно правильно на них отреагировало. Для эмуляции сообщений от клавиатуры можно также воспользоваться функцией keybd_event
, но она посылает сообщение не указанному окну, а активному, что не всегда удобно.
DialogBoxXXXX
) нCreateDialogXXXX
и затем показываются с помощью функции ShowWindow
, использующейся и для обычных, не диалоговых, окон). И модальные, и немодальные окна создаются на основ шаблона, который может храниться в ресурсах приложения или в памяти. В шаблоне можно явно указать имя созданного вами оконного класса диалогового окна или (как это обычно бывает) не указывать его вообще, чтобы был выбран класс, предоставляемый системой для диалоговых окон по умолчанию. Оконная процедура диалогового класса должна передавать необработанные сообщения функции DefDlgProc
.