Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
04-09-2015_19-17-13 / Конспект лекций.doc
Скачиваний:
98
Добавлен:
01.03.2016
Размер:
1.31 Mб
Скачать

17.4 Сообщения Windows

Главная функция приложения WinMain() начинается с объявления структурной переменной msg. Это важнейшая переменная, с помощью которой в программу передается содержимое сообщений Windows. Сообщение представляет собой объект особой структуры, формируемый Windows. Формирование и обеспечение доставки этого объекта в нужное место в системе позволяют управлять работой как самой Windows, так и загруженных Windows-приложений. Инициировать формирование сообщения могут несколько источников: пользователь, само приложение, ОС Windows и другие приложения. Именно наличие механизма сообщений позволяет Windows реализовать многозадачность, которая при работе на одном процессоре является, конечно, псевдомультизадачностью. Windows поддерживает очередь сообщений для каждого приложения. Запуск приложения автоматически подразумевает формирование для него собственной очереди сообщений, даже если приложение и не будет ею пользоваться. Последнее маловероятно, т. к. в этом случае у приложения не будет связи с внешним миром. Каждое сообщение представляет собой пакет из 6 данных, шаблон которых описан в файле windows.h с помощью структуры типа MSG:

typedef struct tagMSG // msg

{

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

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

WPARAM wParam; // Дополнительная информация (слово)

LPARAM lParam; // Дополнительная информация (двойное слово)

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

POINT pt; // Позиция курсора мыши на момент отправления сообщения

} MSG; // Новое имя класса tagMSG

В этом описании тип данных POINT описан во включаемом файле windef.h и представляет собой структуру вида:

typedef struct tagPOINT

{

LONG x;

LONG y;

} POINT.

Рассмотрим подробнее поля структуры msg:

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

в поле message Windows помещает 32-битную константу – идентификатор сообщения, однозначно определяющий тип сообщения. Эти константы содержатся во включаемом файле winuser.h (включается в файле windows.h) и используются в оконной функции оператором switch для принятия решения о том, какая из его ветвей будет исполняться.

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

в поле time Windows записывает информацию о времени, когда сообщение было помещено в очередь сообщений.

поле POINT содержит координаты курсора мыши в момент помещения сообщения в очередь.

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

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

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

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

Рассмотрим процедуру пересылки и состав сообщения на примере сообщения WM_MOUSEMOVE о движении мыши.

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

Главная функция приложения, вызывая в цикле функцию Windows GetMessage(), непрерывно опрашивает очередь сообщений. Как только в очереди обнаруживается сообщение, функция GetMessage() забирает его из очереди и переносит в структурную переменную, предназначенную для приема сообщений (у нас это переменная msg). Вызываемая далее функция DispatchMessage() вызывает оконную функцию того окна, которому предназначено данное сообщение и передает ей через ее аргументы содержимое сообщения из структуры msg. Задача оконной функции – выполнить требуемую обработку поступившего сообщения.

Содержимое сообщения WM_MOUSEMOVE выглядит следующим образом:

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

msg.message; // WM_MOUSEMOVE=0x200

msg.wparam; // Комбинация битовых флагов, инициирующих нажатие клавиш

// мыши, а также клавиш CTRL и SHIFT

msg.lparam; // Позиция курсора мыши относительно рабочей области окна

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

msg.pt; // Позиция курсора мыши относительно границ экрана

Вызывая оконную функцию, функция DispatchMessage() передает ей 4 параметра, которые формируются на основании содержимого поступившего сообщения. В случае сообщения WM_MOUSEMOVE в аргументы функции WndProc() поступают значения msg.hwnd, msg.message, msg.wParam, msg.lParam.

Манипуляции с мышью могут порождать и другие сообщения. Так, нажатие левой клавиши возбуждает сообщение WM_LBUTTONDOWN (код 0х201), отпускание левой клавиши – сообщение WM_LBUTTONUP (код 0х202), нажатие правой клавиши – сообщение WM_RBUTTONDOWN (код 2х204). Сложнее обстоит дело с двойными щелчками клавиш: двойной щелчок левой клавиши порождает целых 4 сообщения: WM_LBUTTOMDOWN, WM_LBUTTONUP, WM_LBUTTONDBCLICK (код 0х203) и снова WM_LBUTTONUP. Программист может обрабатывать как все эти сообщения, так и только сообщения о двойном щелчке, не обращая внимание на все остальные. Механизм образования всех этих сообщений в точности такой же, как и для сообщения WM_MOUSEMOVE, даже пакеты данных для этих сообщений не различаются.

Схожим образом формируются сообщения и от клавиатуры.

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

Содержимое сообщения WM_KEYDOWN выглядит следующим образом:

msg.hwnd; // Дескриптор активного окна

msg.message; // WM_KEYDOWN=0x100

msg.wparam; // Код виртуальной клавиши

msg.lparam; // Дополнительная инф-ция (скен-код, счетчик повторения, флаг на-

// жатия ALT и т. д.)

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

msg.pt; // Позиция курсора мыши относительно границ экрана

Код виртуальной клавиши в этом сообщении – это специфический для системы Windows код, присвоенный каждой клавише. Виртуальные коды не совпадают со скен-кодами, хотя частично совпадают с кодами ASCII (для цифровых клавиш формируются коды ASCII цифр, а для алфавитных – коды ASCII прописных букв). Сообщение WM_KEYDOWN используется, как правило, не для ввода текста, а для управления ходом управления программы по нажатию каких-либо клавиш.

Предусмотрены и другие сообщения, связанные с клавиатурой. Так, отпускание любой клавиши формирует сообщение WM_KEYUP (код 0х101), нажатие клавиши вместе с клавишей ALT – сообщение WM_SYSKEYDOWN (код 0х104) и т. д.

Рассмотренные сообщения относятся к сообщениям нижнего уровня – они оповещают об аппаратных событиях практически без всякой их обработки Windows. Некоторые аппаратные события предварительно обрабатываются Windows, и в приложение поступает уже результат этой обработки. Так, при нажатии левой клавиши, мыши над строкой меню аппаратное прерывание поглощается системой Windows, и вместо сообщения WM_LBUTTONDOWN формируется сообщение WM_COMMAND (код 0х111), в число параметров которого входит идентификатор того пункта меню, над которым был курсор мыши. Это избавляет нас от необходимости анализа положения курсора мыши и выделения всех положений, соответствующих прямоугольной области данного пункта меню. Другой пример – сообщение WM_NCLBUTTONDOWN (код 0хА1), которое формируется Windows, если пользователь нажал левую клавишу мыши в нерабочей области окна, т. е. на его заголовке (с целью, например, перетащить окно в другое место экрана).

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

Рассмотрим, например, сообщение WM_CREATE. Оно генерируется системой Windows в процессе создания окна, чтобы программист, перехватив это сообщение, мог выполнить необходимые инициализирующие действия: установить системный таймер, загрузить требуемые ресурсы (шрифты, растровые изображения), открыть файлы с данными и т. д. Сообщение WM_CREATE не поступает в очередь сообщений приложения и, соответственно, не изымается оттуда функцией GetMessage(). Вместо ‘того Windows непосредственно вызывает оконную функцию WndProc() и передает ей необходимые параметры. С точки зрения программиста не имеет особого значения, каким образом вызывается оконная функция – функцией DispatchMessage(), вызванной в приложении, или непосредственно программами Windows. Иногда, однако, полезно иметь в виду, что при обработке, например, сообщения WM_MOUSEMOVE, все содержимое этого сообщения находится в структурной переменной msg, а при обработке WM_CREATE мы имеем дело только с параметрами, переданными Windows в оконную функцию. В переменной msg и в это время находится старое, уже обработанное сообщение, т. е. мусор.

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

Соседние файлы в папке 04-09-2015_19-17-13