ПРИЛОЖЕНИЕ 2.


Основные типы сообщений Windows

В настоящее время в системе Windows имеется более 900 стандартных сообщений. К счастью, нет необходимости знакомиться со всеми, поскольку большинство из них используются очень редко. Например, большое количество сообщений характерно для одного типа окна. Другие сообщения играют особую роль в совместном использовании данных или реализации стандарта многодокументного интерфейса (MDI). Третьи проходят по нашему циклу сообщений, но никогда не используются. Это внутренние сообщения, которые Windows создает для своих собственных целей. Все сообщения имеют имена, которые определены в файле <winuser.h> следующим образом:

#define WM_COMMAND 0x0lll

ИЛИ

#define WM_PAINT 0x000F

Префикс WM_ говорит о том, что речь идет об "оконном сообщении" (от Window Message). Эти символические имена обозначают числовые значения. Кроме WM_ широко используются и другие префиксы: ЕМ_ (Edit Message) — для сообщений элемента управления Edit, BM_ (Button Message) — для сообщений элемента управления Button, LM_ (Listbox Message) — для сообщений элемента управления Listbox и т. д. Помимо этого, вы можете создавать и собственные сообщения.

Чтобы как-то систематизировать такое огромное количество сообщений, я разделил их на следующие категории:

Аппаратные 

Входные данные от мыши и клавиатуры

 Организация окна 

Уведомление, требование действия, запрос

Организация интерфейса  пользователя  

Меню, указатель мыши, линейка прокрутки, пользователя   блоки диалога, MDI.

Завершение работы 

Закрытие прикладной программы или системы 

Частные 

Элементы управления: кнопка, редактор и т. д.

Уведомление о системном ресурсе 

 Изменение цвета, шрифтов, буферизация печати, ресурсе режимы работы устройства

Обмен данными 

Буфер обмена и динамический обмен данными

 Внутрисистемные 

Недокументированные сообщения

 

Аппаратные сообщения

Оконная процедура получает сообщения, инициируемые тремя частями аппаратного обеспечения: клавиатурой, мышью и системным таймером. Все они генерируют аппаратные прерывания. Поскольку диспетчеризация Windows не действует в режиме прерываний, аппаратные события должны быть буферизованы. Это обеспечивает обработку событий в порядке их поступления. Например, когда вы нажимаете клавишу <К>, прерывание уведомляет систему о том, что приготовлены данные от клавиатуры. Драйвер клавиатуры отыскивает эти данные и создает элемент в первичной очереди, откуда система их передает в очередь приложения, а точнее, конкретного потока. Когда наступает его очередь, сообщения, содержащие информацию о клавише <К>, направляются в соответствующую оконную процедуру. Сообщения от мыши и системного таймера обрабатываются аналогично. В табл. П2.1— П2.4 представлены основные сообщения, которые формируются в ответ на работу аппаратного обеспечения.

Таблица П2.1. Сообщения от мыши в клиентской области окна

WM_LBUTTONDBLCLK

 WM_LBUTTONDOWN

 WM_LBUTTONUP

 WM_MBUTTONDBLCLK

 WM_MBUTTONDOWN

 WM_MBUTTONUP

 WM_MOUSEMOVE

 WM_RBUTTONDBLCLK

 WM_RBUTTONDOWN

 WM_RBUTTONUP

Двойное нажатие левой кнопки 

Нажатие левой кнопки 

Отпускание левой кнопки

 Двойное нажатие средней кнопки

 Нажатие средней кнопки

 Отпускание средней кнопки 

Перемещение мыши 

Двойное нажатие правой кнопки

 Нажатие правой кнопки 

Отпускание правой кнопки

Таблица П2.2. Сообщения от мыши в неклиентской области окна

WM_NCLBUTTONDBLCLK

 WM_NCLBUTTONDOWN

Двойное нажатие левой кнопки 

Нажатие левой кнопки

WM_NCLBUTTONUP

 WM_NCMBUTTONDBLCLK

 WM_NCMBUTTONDOWN

 WM_NCMBUTTONUP

 WM_NCMOUSEMOVE

 WM_NCRBUTTONDBLCLK

 WM_NCRBUTTONDOWN

 WM_NCRBUTTONUP

Отпускание левой кнопки 

Двойное нажатие средней кнопки 

Нажатие средней кнопки 

Отпускание средней кнопки 

Перемещение мыши 

Двойное нажатие правой кнопки 

Нажатие правой кнопки 

Отпускание правой кнопки

Таблица П2.3. Сообщения от клавиатуры

WM_CHAR

 WM_DEADCHAR

 WM_KEYDOWN

 WM_KEYUP

 WM_SYSCHAR

 WM_SYSDEADCHAR

 WM_SYSKEYDOWN

 WM_SYSKEYUP

Ввод символа 

Диакритический знак (умляут, ударение и т. д.)

 Была нажата клавиша 

Была отпущена клавиша

 Ввод специального символа 

Специальный диакритический знак 

Была нажата специальная клавиша

 Была отпущена специальная клавиша

Таблица П2.4. Сообщения от таймера

WMJTIMER

Истекло заданное время

Сообщения от таймера помешаются в очередь так же, как и сообщения от мыши и клавиатуры (т. е. таймеры в системе Windows не являются точными).

Сообщение WM_MOUSEMOVE заслуживает особого упоминания, т. к. обрабатывается особым образом, чтобы избежать переполнения очереди аппаратных событий. Дело в том, что при быстром перемещении мыши могут произойти сотни прерываний. Во избежание переполнения очереди система Windows хранит только одно сообщение о перемещении мыши в каждый момент времени. Когда приходит новое сообщение, Windows проверяет, есть ли уже подобное. Если оно есть, то в нем обновляется информация о положении. Новое сообщение помешается в очередь сообщений только в том случае, если сообщения о перемещении мыши еще не было.

Сообщения от клавиатуры делятся на два основных типа: обычные и системные. Обычно системные сообщения от клавиатуры (начинающиеся на WM_SYS...) игнорируются, т. к. оконная процедура, устанавливаемая по умолчанию, превращает их в соответствующую системную команду.

Сообщения обслуживания окна

Здесь собраны наиболее часто используемые сообщения, и вам следует хорошенько разобраться с каждым из них. К сожалению, имена не окажут вам большой помощи. Начнем с того, что сообщения этой группы можно разбить на три части: уведомление, требование действия и запрос (табл. П2.5— П2.7).

Таблица П2.5. Оконные сообщения: уведомление

WM_ACTIVATE

 WM_ACTIVATEAPP

 WMJDREATE

 WM_DESTROY

 WM_ENABLE

 WM_KILLFOCUS

 WM_MOUSEACTIVATE

 WM_MOVE

 WM_SETFOCUS

 WM_S1ZE

Окно активно

Приложение активно 

Окно было создано 

Окно было уничтожено 

Был разрешен ввод в окно

 Окно потеряло фокус ввода от клавиатуры 

Окно станет активным после нажатия кнопки мыши 

Окно было перемещено 

Окно получило фокус ввода от клавиатуры

 Окно изменило размер

Таблица П2.6. Оконные сообщения; требование действия

WM_CLOSE

 WM_ERASEBKGND

 WMJCONERASEBKGND

            WM_NCACTIVATE

                WM_NCCREATE

 WM_NCDESTROY

 WM_NCPAINT

Закрыть (уничтожить) окно 

Удалить фон

Удалить фон окна, показываемого в виде пиктограммы

Изменить заголовок окна для показа активного состояния

Создать неклиентскую область окна 

Уничтожить неклиентскую область окна

 Перерисовать неклиентскую область

WM_PAINT

 WM_PAINTICON

WM_SETREDRAW

 WM_SETTEXT

 WM_SHOWWINDOW

Перерисовать клиентскую область

Перерисовать клиентскую область окна, показываемого в виде пиктограммы

Запретить перерисовку окна 

Изменить текст окна 

Изменить режим отображения окна

Таблица П2.7. Оконные сообщения: запросы

WM_GETMINMAXINFO  

                 

WM_GETTEXT        

 

                    WM_GETTEXTLINGTH                        

WM_NCCALCSIZE

  WM_QUERYNEWPALETTE

                                WM_QUERYOPEN 

Запрос информации о минимальном/максимальном размере окна

Запрос текста заголовка окна, а для окон, не имеющих заголовка (например, для кнопок) — текста, размещенного в окне

Запрос длины текста окна 

Запрос размеров клиентской области 

Запрос существования новой палитры

Запрос возможности открытия окна, отображаемого в виде пиктограммы

Сообщение-уведомление говорит оконной процедуре о том, что состояние окна было изменено. При этом оконная процедура вовсе не должна выполнять действие, обозначенное именем сообщения. Например, сообщение WM_MOVE не является запросом на некоторое перемещение. Наоборот, оно является "сообщением после действия" и напоминает, что окно уже было перемещено. Обратите внимание, что из сообщения не ясно, каким образом произошло перемещение. Это могло быть результатом действий пользователя, равно как и другой программы. В любом случае сообщения-уведомления представляют собой одностороннюю связь с оконной процедурой.

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

рода сообщения самому, как в случае с сообщением WM_PAINT. При этом нередко нужно воспроизвести все действия обработчика, устанавливаемого по умолчанию.

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

Сообщения об организации интерфейса пользователя

Эта группа содержит сообщения для других объектов пользовательского интерфейса, включающих меню прикладной программы, указатель мыши, линейки прокрутки, блоки диалога и их элементы управления, а также сообщения, используемые для поддержки многодокументного интерфейса (MDI). Основные сообщения приводятся в табл. П2.8—П2.13.

Таблица П2.8. Сообщения от меню

WM_COMMAND

 WMJNITMENU

      WM_INITMENUPOPUP

                    

WM_MENUCHAR        

        WM_MENUSELECT

Был выбран пункт меню

Уведомление о возможности изменить меню перед его активизацией

Уведомление о возможности изменить пункты всплывающего меню перед его отображением на экране

Для выбора меню использована мнемоническая клавиша

 Пользователь просматривает меню

Таблица П2.9. Системные команды

WM_SYSCOMMAND

Была выбрана системная команда

Таблица П2.10. Сообщения от указателя мыши

WM_NCHITTEST

 WM_SETCURSOR

Передача в окно текущего положения указателя мыши

Уведомление окну при перемещении мыши с возможностью изменить курсор в зависимости от положения указателя

Таблица П2.11. Сообщения линейки прокрутки

WMJHSCROLL

 WM_VSCROLL

Была нажата горизонтальная линейка прокрутки

Была нажата вертикальная линейка прокрутки

Таблица П2.12. Сообщения блока диалога и его элементов управления

WM_COMMAND

 WM_COMPAREITEM

                WM_CTLCOLOR

 WM_DELETEITEM

 

WM_DRAWITEM

           WM_GETDLGCODE

 

WM_GETFONT

              WM_INITDIALOG

 WM_MEASUREITEM 

                   WM_SETFONT

Управляющая связь с блоком диалога

Посылается родителю с запросом на сравнение двух элементов для сортировки

Управляющий запрос на установку цветов

Уведомление, направляемое элементам управления Listbox и Combobox.o том, что удален элемент

Запрос родителю пользовательских элемента управления и меню на рисование

Запрос оконной процедуре, какие типы сообщений будут ею впоследствии обрабатываться

Запрос дескриптора основного шрифта отображения 

Запрос на инициализацию диалогового окна

Запрос родителю элемента управления на обеспечение его размеров при прорисовке

Требование к элементу управления: использовать данный шрифт

Таблица П2.13. Сообщения многодокументного интерфейса (MDI)

WM_CHILDACTIVATE

                  WM_MDIACTIVATE

                   WM_MDICASCADE

                      WM_MDICREATE

                WM_MDIGETACTIVE

        WM_MDIICONARRANGE

Объявляет порождающему окну об активизации дочернего окна

Объявляет дочернему окну MDI, что оно получает или теряет активизацию

Требование оформить дочерние окна MDI в каскадной (ступенчатой) форме

Требование окну клиента MDI создать дочернее окно

Запрос окна клиента MDI о текущем активном дочернем окне

Требование упорядочить расположение дочерних окон MDI, отображаемых в виде пиктограмм

WM_MDIMAXIMIZE

                  WM_MDINEXT

           WM_MDIRESTORE

          WM_MDISETMENU

                  WM_MDITITLE

Требование максимизировать дочерние окна MDI

Требование активизировать следующее дочернее окно MDI

Требование восстановить дочернее окно MDI в его предыдущем состоянии

Настраивает меню для текущего дочернего окна MDI

Требование оформить дочерние окна MDI в форме черепичного (без перекрытий) расположения

 

Сообщения о завершении

Эта группа сообщений самая малочисленная, но все они очень важны, т. к. используются для управления завершением приложений (табл. П2.14)

  Таблица П2.14. Завершение работы приложения и системы

WM_QUIT

 WM_QUERYENDSESSION

                      WM_ENDSESSION

 

Требование на завершение приложения

Запрос готовности приложения к завершению работы всей системы

Уведомление о результатах запроса на завершение работы системы

 

Частные сообщения

Очень просто определить собственные сообщения и использовать их для связи между различными окнами, которые вы создаете. При определении частного сообщения необходимо использовать область значений, начинающуюся с WM_USER, которая определена в <winuser.h> следующим образом:

#define WM_USER 0x0400

Например, если мы хотим работать с окнами, которые показывают числа, то могли бы контролировать появление чисел различных систем счисления с помощью следующих частных сообщений (РМ_ — префикс "частного сообщения" от Private Message):

#define PM_DECIMAL WM__USER + 0

#define PM_BINARY WM_USER + 1

#define PM_HEX WM_USER + 2

#define PM_OCTAL WMJJSER + 3

Кроме того, есть несколько частных системных сообщений (табл. П2.15).

Таблица П2.15. Частные системные сообщения

WM_CANCELMODE

          WM_ENTERIDLE

Требование системы отменить режим, например, захват мыши

Сообщает, что система находится в режиме ожидания

 

Информационные сообщения системных ресурсов

Имеется всего восемь сообщений с уведомлением об изменении некоторых системных ресурсов (табл. П2.16). Они посылаются окну верхнего уровня каждой программы при изменении системного ресурса. Например, когда добавляются или удаляются шрифты в системе, распространяется сообщение WM_FONTCHANGE. А когда пользователь изменяет системные цвета или системное время, отправляются сообщения WM_SYSCOLORCHANGE или WM_TIMECHANGE, соответственно. Типичной реакцией на часть такого рода сообщений является немедленная запись произведенных изменений, т. е. сохранение выполненной работы. Судите сами.

Таблица П2.16. Сообщения с уведомлением об изменениях системных ресурсов

WM_COMPACTING

 WM_DEVMODECHANGE

 WM_FONTCHANGE

 WM_PALETTECHANGED

 WM_SPOOLERSTATUS

 WM_SYSCOLORCHANGE

 WM_TIMECHANGE

 WM_WININICHANGE

Недостаточно системной памяти

 Изменилась настройка принтера 

Изменились установленные в системе шрифты 

Палитра аппаратных цветов изменена

 Задание было удалено из очереди буфера печати

 Один или более системных цветов изменены

Изменилось системное время 

Изменился файл инициализации <win.ini>

Не всякое изменение представляет интерес для каждой программы. Например, программа, использующая таймер, вероятно, будет проверять новое значение времени при получении сообщения WM_TIMECHANGE. Но если она не работает со шрифтами, то, скорей всего, сообщение WM_FONTCHANGE будет проигнорировано. Поскольку большинство программ использует системные цвета, то они будут реагировать на сообщение WM_SYSCOLORCHANGE, организуя перерисовывание новыми цветами.

 

Сообщения о совместном использовании данных

В Windows есть сообщения, которые посылаются при совместном использовании данных для поддержки механизмов работы с буфером обмена (clipboard) и динамического обмена данными (DDE), которые определены в файлах <winuser.h> и <dde.h>, соответственно. И хотя полное обсуждение этого вопроса выходит за рамки книги, мы приведем список сообщений этой группы (табл. П2.17—П2.18).

Таблица П2.17. Сообщения от буфера обмена

WM_ASKCBFORMATNAME

 WM_CNANGECBCHAIN

     WM_DESTRIYCLIPBOARD

 WM_DRAWCLIPBOARD

 WM_HSCROLLCLIPBOARD

 WM_PAINTCLIPBOARD

 WM_RENDERALLFORMATS

                 WM_RENDERFORMAT

                   WM_SIZECLIPBOARD

 WM_VSCROLLCLIPBOARD

Запрашивает имя формата буфера обмена 

Уведомление об изменении цепочки просмотра

 Содержимое буфера обмена уничтожено

 Содержимое буфера обмена изменено

 Горизонтальная прокрутка буфера обмена 

Запрашивает рисование буфера обмена

Запрашивает данные для всех ранее объявленных форматов буфера обмена

Запрашивает данные для ранее объявленного формата буфера обмена

Размер буфера обмена изменен 

Вертикальная прокрутка буфера обмена

Таблица П2.18. Сообщения DDE

WM_DDE_ACK

 WM_DDE_ADVISE

              WM_DDE_DATA

        WM_DDE_EXECUTE

         WM_DDE_INITIATE

Подтверждение приема

Запрос от пользователя DDE об установлении постоянного канала передачи данных

Направляет элемент данных от DDE-сервера клиенту DDE 

Дает указание DDE-серверу выполнить серию команд 

Вход в DDE-сервер

WM_DDE_POKE

          WM_DDE_REQUEST

                                            WM_DDE_TERMINATE

 WM_DDE_INADVISE

Запрос пользователя серверу об обновлении определенного элемента данных

Однократный запрос пользователя на информацию 

 

Выход из DDE-сервера

Завершить постоянный канал передачи данных, инициализированный сообщением WM_DDE_ADVISE

Внутрисистемные сообщения

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

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