Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лабораторный практикум «Основы разработки приложений Windows» книга 1.DOC
Скачиваний:
107
Добавлен:
10.05.2014
Размер:
721.41 Кб
Скачать

Сообщения Windows и цикл их обработки

Цикл обработки сообщений в простейшем виде состоит из одного предложения:

while(GetMessage(&msg,NULL,0,0))

DispatchMessage(&msg);

В этом бесконечном (если его не разорвать изнутри) цикле вызывается функция Windows GetMessage(), и, если она возвращает ненулевое значение, вызывается функцияDispatch­Mes­sage(). Назначение функцииDispatchMessage()– вызов оконной функции приложения с передачей ей параметров, извлеченных из пришедшего в приложение сообщения (вспомним, что имя нашей оконной функции мы сообщили Windows в процессе регистрации класса окна).

Для того, чтобы разобраться в деталях этого очень важного механизма, нам надо познакомиться поближе с самим понятием сообщений.

Сообщения являются реакцией системы Windows на различные происходящие в системе события: движение мыши, нажатие клавиши, срабатывание таймера и т. д. Отличительным признаком сообщения является его код, который может принимать значения (для системных сообщений) от 1 до 0x3FF. Каждому коду соответствует своя символическая константа, имя которой достаточно ясно говорит об источнике сообщения. Так, при движении мыши возникают сообщения WMMOUSEMOVE(код 0x200), при нажатии на левую клавишу мыши – сообщениеWMLBUTTONDOWN(код 0x201), при срабатывании таймера –WMTIMER(код 0x113).

Перечисленные события относятся к числу аппаратных; однако сообщения могут возникать и в результатепрограммныхдействий системы или прикладной программы. Так, по ходу создания и вывода на экран главного окна Windows последовательнопосылает в приложение целую группу сообщений, сигнализирующих об этапах этого процесса: WMGETMINMAXINFO – для уточнения размеров окна, WMERASEBKGND– при заполнении окна цветом фона,WMSIZE– при оценке размеров рабочей области окна,WMPAINT– для получения от программы информации о содержимом окна и многие другие. Некоторые из этих сообщений Windows обрабатывает сама; другие обязана обработать прикладная программа.

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

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

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

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

Рис. 1.2. Процедура создания и пересылки сообщения от мыши

Рассмотрим, из чего состоит каждое сообщение. В начале главной функции приложения WinMain объявлена структурная переменная msg. Это важнейшая переменная, с помощью которой в программу передается содержимое сообщений Windows. Каждое сообщение представляет собой пакет из шести данных, описанных в файлеWINUSER.Hс помощью структуры типаMSG:

typedef struct tagMSG {

HWND hwnd;//Дескриптор окна, которому адресовано сообщение

UINT message;//Код данного сообщения

WPARAM wParam;//Первая группа параметров сообщения

LPARAM lParam;//Вторая группа параметров сообщения

DWORD time;//Время отправления сообщения

POINT pt;//Позиция курсора мыши

} MSG;//Новое имя для типа tagMSG

Часть этих параметров (hwnd, message, time иpt) имеет одинаковый смысл для всех сообщений; параметры жеwParam иlParam для каждого сообщения содержат специфические данные. Для сообщенияWMMOUSEMOVEструктурная переменнаяmsg заполняется следующей информацией:

  • msg.hwnd– дескриптор окна под курсором мыши;

  • msg.message– код сообщенияWMMOUSEMOVE=0x200;

  • msg.wParam– комбинация битовых флагов, индицирующих состояние клавиш мыши (нажаты/не нажаты), а также клавиш клавиатуры Ctrl и Shift;

  • msg.lParam– позиция курсора мыши относительно рабочей области окна на момент отправления сообщения;

  • msg.time– время отправления сообщения;

  • msg.pt– позиция курсора мыши относительно границ экрана.

Активизируя оконную функцию, функция Dispatch­Mes­sage()передает ей первые четыре из перечисленных выше шести параметров; если программе для организации правильной реакции на пришедшее сообщение требуются оставшиеся два параметра, их можно извлечь непосредственно из переменнойmsg.

Манипуляции с мышью могут порождать и другие сообщения. Так, нажатие левой клавиши мыши возбуждает сообщение WM­LBUT­TONDOWN(код0x201), отпускание левой клавиши – сообщениеWMLBUTTONUP(код0x202), нажатие правой клавиши – сообщениеWMRBUTTONDOWN(код 0x204). Сложнее обстоит дело с двойными щелчками клавиш. Двойной щелчок левой клавиши порождает целых четыре сообщения:WMLBUTTONDOWN,WM­LBUT­TON­UP,WMLBUTTONDBLCLKи сноваWMLBUTTONUP. Программист может обрабатывать как все эти сообщения, так и только сообщения о двойном нажатии, не обращая внимания на остальные. Механизм образования всех этих сообщений в точности такой же, как и для сообщенияWMMOUSEMOVE(аппаратное прерывание, формирование драйвером мыши пакета данных, установка сообщения в системную очередь, пересылка сообщения в очередь приложения, вызов оконной функции). Даже пакеты данных для этих сообщений не различаются.

Схожим образом формируются сообщения, например, от клавиатуры: WMKEYDOWN о нажатии любой “несистемной” клавиши (т. е. любой клавиши, не сопровождаемой нажатием клавишиAlt),WMKEYUP об отпускании несистемной клавиши,WMSYSKEYDOWN о нажатии “системной” клавиши (т. е. любой клавиши совместно с клавишейAlt)и др.

Рассмотренные сообщения относятся к сообщениям нижнего уровня – они оповещают об аппаратных событиях практически без всякой их обработки Windows. Некоторые аппаратные события предварительно обрабатываются Windows, и в приложение поступает уже результат этой обработки. Так, при щелчке левой клавишей мыши над строкой меню, помимо сообщения WMLBUT­TON­DOWNформируется сообщениеWMCOMMAND, в число параметров которого входит идентификатор того пункта меню, над которым был курсор мыши в момент щелчка. Это избавляет нас от необходимости анализа положения курсора мыши и выделения всех положений курсора, входящих в прямоугольную область данного пункта меню.

Рассмотренный механизм прохождения сообщений справедлив, главным образом, для аппаратных сообщений. Большая часть программных сообщений, т. е. сообщений, прямо не связанных с аппаратными событиями, а возникающих по ходу протекания программных процессов в приложении или в самой Windows, обслуживаются системой иным образом. Рассмотрим, например, сообщение WMCREATE. Оно формируется системой в процессе создания окна, чтобы программист, перехватив это сообщение, мог выполнить необходимые инициализирующие действия: открыть файлы с данными, установить системные таймеры, создать дополнительные дочерние окна и т. д. СообщениеWMCREATE не поступает в очередь сообщений приложения. Вместо этого Windows непосредственно вызывает оконную функциюWndProc()с передачей ей необходимых параметров (рис. 1.3). С точки зрения программиста обычно не имеет особого значения, каким образом вызывается оконная функция – функциейDispatchMessage() или непосредственно программами Windows. Полезно, однако, иметь в виду, что при обработке, например, сообщенияWMMOUSEMOVEвсе содержимое этого сообщения находится в структурной переменнойmsg, а при обработкеWMCREATEмы имеем дело только с параметрами, переданными Windows в оконную функцию. В переменнойmsgв это время находится старое, уже обработанное сообщение, т. е. “мусор”.

Рис. 1.3. Прохождение программного сообщения WM_CREATE

Аналогично, т. е. помимо очереди сообщений приложения и структурной переменной msg, обрабатываются, например, сообщенияWMINITDIALOG(инициализация диалога),WMSYSCOM­MAND(выбор пунктов системного меню),WMDESTROY(уничтожение окна) и многие другие.

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

Рис. 1.4. Действие цикла обработки сообщений

Как уже упоминалось, функция GetMessage()анализирует очередь сообщений приложения. Если в очереди обнаруживается сообщение, функцияGetMessage()изымает его из очереди и передает в структуруmsg, после чего завершается с возвратом значенияTRUE. При отсутствии сообщений в очереди система переводит цикл обработки сообщений в спящее состояние. Приложение, находящееся в спящем состоянии, не потребляет процессорного времени и не тормозит работу системы. Усыпление данного приложения позволяет Windows эффективно обслуживать другие приложения. Появление в очереди какого-либо сообщения снова вызывает к жизни функциюGetMessage(), которая выполняет предназначенную ей работу – перенос сообщения из очереди сообщений в структурную переменнуюmsg.

В любом случае функция GetMessage()завершится (с возвратом значенияTRUE) лишь после того, как очередное сообщение попадет в переменнуюmsg.

Особая ситуация возникает, если функция GetMessage()обнаруживает в очереди сообщениеWMQUITс кодом 0x12. В этом случаеGetMessage()сразу же завершается с возвратом значенияFALSE. Однако циклwhileвыполняется, лишь еслиGetMes­sage()возвращаетTRUE. ВозвратFALSEприводит к завершению цикла и переходу на предложение

return 0;

т. е. к завершению функции WinMain()и всего приложения. Таким образом, условием завершения приложения является появление сообщенияWMQUIT. Как оно возникает, будет рассмотрено в следующем подразделе.