Цикл обработки начинается с извлечения сообщений из очереди при помощи функции

       BOOL GetMessage(MSG FAR* lpmsg,HWND hwnd, UINT uMsgFilterMin,UINT uMsgFilterMax);

Если при вызове этой функции указать вторым аргументом NULL, то программа будет получать сообщения от всех окон, созданных программой. При помощи параметров uMsgFilterMin и uMsgFilterMax можно отфильтровать сообщения, получаемые программой. Если на их месте передать 0, то программа будет получать все сообщения.

После вызова функции GetMessage приложение получает структуру msg типа MSG с информацией о сообщении. Структура MSG содержит информацию об окне, которому предназначено сообщение, численное значение самого сообщения, время и координаты (для сообщений от мыши) возникновения сообщения, а также два дополнительных параметра wParam и lParam, смысл и значение которых зависят от особенностей сообщения.

Каждое получаемое приложением сообщение (за исключением WM_QUIT) направлено одному из окон приложения. Поскольку приложение не должно прямо вызывать функцию обработки окна, для передачи сообщения нужному окну используется функция

       LONG DispatchMessage(const MSG FAR* lpmsg);

Эта функция передает msg обратно в Windows. Windows отправляет сообщение для его обработки соответствующей оконной процедуре – таким образом Windows вызывает оконную процедуру.

После того как оконная функция обработает сообщение, Windows возвращает управление в приложение к следующему за вызовом DispatchMessage коду, цикл обработки сообщений в очередной раз возобновляет работу, вызывая GetMessage. Если поле message сообщения msg, извлеченного из очереди сообщений, равно любому значению, кроме WM_QUIT, то функция GetMessage возвращает ненулевое значение. Сообщение WM_QUIT, извлеченное из очереди приложения, заставляет прервать цикл обработки сообщений.

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

       BOOL TranslateMessage(const MSG FAR* lpmsg);

 

Завершение работы приложения

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

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

Когда функция GetMessage извлекает сообщение WM_QUIT из очереди, она возвращает нуль, что приводит к завершению работы приложения. При завершении приложения следует аккуратно освобождать занятые ресурсы - не стоит полагаться в этом на Windows.

Фрагмент кода функции WinMain, в котором осуществляется завершение работы приложения:

      ...

       // цикл обработки сообщений

       while(GetMessage(&msg, NULL, 0, 0)) {... }

       // завершается после получения WM_QUIT

      ...

       return TRUE;                    // завершение работы приложения

 

Оконная процедура

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

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

Оконная процедура всегда связана с определенным классом окна, который регистрируется при помощи функции RegisterClass. Функция CreateWindow создает окно на основе определенного класса окна. На основе одного и того же класса можно создать несколько окон.

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

       LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

Все четыре параметра оконной процедуры идентичны первым четырем полям структуры MSG. Первым параметром является дескриптор окна, получающего сообщение. Если в программе создается несколько окон на основе одного и того же класса окна (и следовательно одной и той же оконной процедуры), тогда параметр hWnd идентифицирует конкретное окно, которое получает сообщение.

Функция окна имеет одно очень важное свойство: она вызывается непосредственно Windows и не может вызываться приложением напрямую. Как и большинство функций Windows, в функции окна используется соглашение о связях языка Паскаль, поэтому объявление функции CALLBACK обязательно.

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

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

       {

       return(DefWindowProc(hWnd, message, wParam, lParam));

       }

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

 

Обработка сообщений

Каждое получаемое окном сообщение идентифицируется номером, который содержится в параметре msg оконной процедуры. Если оконная процедура обрабатывает сообщение, то ее возвращаемым значением должен быть 0.

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

 


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: