92978b58

Функция окна


Другим базовым понятием, с которым вы неизбежно столкнетесь при создании приложений для Presentation Manager, является так называемая функция окна .

Чтобы вам было понятно назначение функции окна, проведем аналогию окон, создаваемых системой Presentation Manager, с объектами в языке программирования C++. Там объект определяется как структура данных и набор методов, предназначенных для обработки этих данных. В качестве методов выступают функции. Среди этих методов существуют два особых - конструктор и деструктор. Эти методы выполняют, соответственно, создание и уничтожение объекта.

Окно, созданное с помощью средств Presentation Manager, можно также рассматривать как объект, состоящий из некоторой структуры данных и методов, реализованных с помощью функции окна. При этом функция окна полностью определяет свойства окна.

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

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

Самое интересное заключается в том, что после определения функции окна приложение... никогда не вызывает эту функцию!

Зачем, спросите вы, приложение создает функцию, которую оно не вызывает?

Дело в том, что функция окна вызывается системой Presentation Manager, когда над окном выполняются какие-либо действия. После вызова функция окна анализирует параметры, полученные ей от Presentation Manager, и выполняет соответствующий фрагмент, определяющий реакцию окна на данное действие.

Если вы знакомы со структурой драйверов MS-DOS , то вам будет понятна аналогия между функцией окна и функцией прерывания драйвера. Драйвер создает функцию прерывания, которая обрабатывает посылаемые ему команды, однако сам драйвер никогда напрямую не вызывает эту функцию.

Таким образом, для каждого окна приложение должно определить функцию окна и каким-то образом (каким - вы узнаете позже) указать системе Presentation Manager, что для данного окна будет использована именно эта функция. После создания окна система Presentation Manager будет при необходимости вызывать функцию окна.


Теперь настало время заняться функцией окна, которое было создано функцией main и после регистрации главного окна приложения, зажило своей жизнью.

Рискуя быть навязчивыми, скажем еще раз, что приложение никогда не должно вызывать функцию окна напрямую. Ей передает управление система Presentation Manager, поэтому она вызывается извне приложения. Такие функции называют функциями обратного вызова.

Прототип функции окна мы привели ниже. Учтите, что имя функции окна может быть любым. Главное, чтобы вы правильно указали это имя при регистрации класса окна функцией WinRegisterClass .

MRESULT EXPENTRY WndProc( HWND hWnd, // идентификатор окна ULONG msg, // код сообщения MPARAM mp1, // первый параметр сообщения MPARAM mp2); // второй параметр сообщения

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

Сравните параметры функции окна со структурой, в которую записывает сообщение функция WinGetMsg :

typedef struct _QMSG { HWND hwnd; // идентификатор окна ULONG msg; // код сообщения MPARAM mp1; // первый параметр сообщения MPARAM mp2; // второй параметр сообщения ULONG time; // время возникновения сообщения POINTL ptl; // позиция курсора мыши во время // возникновения сообщения ULONG reserved; // зарезервировано } QMSG ; typedef QMSG *PQMSG;



Как видите, функция окна получает сообщение в "разобранном" виде, удобном для анализа.

Анализ выполняется при помощи проверки кода сообщения, например, так, как это показано в следующем фрагменте кода:

MRESULT EXPENTRY WndProc(HWND hWnd, ULONG msg, MPARAM mp1, MPARAM mp2) { switch (msg) { case WM_CREATE : { . . . }

case WM_DESTROY : { . . . }

case WM_ERASEBACKGROUND : return(MRFROMLONG(1L));

case WM_BUTTON1DOWN : { . . . }

default: return(WinDefWindowProc (hWnd, msg, mp1, mp2)); } }

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


Функция WndProc обрабатывает сообщения, поступающие в окно Client Window нашего приложения.

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

Сообщение WM_ERASEBACKGROUND посылается в окно для того, чтобы функция окна подтвердила необходимость стирания фона окна Client Window . В зависимости от значения, которое возвратит функция окна в ответ на это сообщение, система Presentation Manager будет принимать решение о необходимости стирания. Если функция вренет значение 1, стирание следует выполнить, если 0 - нет. Экспериментируя с приложением, вы можете попробовать изменить возвращаемое значение на нулевое. Вы увидите, что при перемещении окно приложения Client Window не будет перерисовываться.

Более детально процесс рисования в окне мы рассмотрим позже. А сейчас займемся сообщениями WM_BUTTON1DOWN и WM_BUTTON2DOWN .

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

Вместе с сообщениями WM_BUTTON1DOWN и WM_BUTTON2DOWN передаются параметры - текущие координаты курсора мыши. Координата по оси X передается через параметр mp1, а координата по оси Y - через параметр mp2.

Для того чтобы отобразить эти координаты на экране, мы с помощью функции sprintf подготавливаем текстовую строку и вызываем функцию WinMessageBox . Обратите внимание, что в качестве второго параметра мы указываем идентификатор окна hWnd, который передается в функцию окна через первый параметр.

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

Все остальные сообщения, попадающие в функцию окна, мы передаем функции WinDefWindowProc . Это необходимо не только для правильной работы нашего приложения, но и для нормальной работы системы Presentation Manager. Блокируя обработку сообщений, мы можем привести операционную систему в такое состояние, когда потребуется ее перезапуск.

Обратите также внимание на то, что в нашей функции окна мы не обрабатываем сообщения WM_CREATE и WM_DESTROY , поступающие, соответственно, при создании и уничтожении окна. Так как наше приложение не выполняет в этих случаях никаких дополнительных действий, мы передаем сообщения WM_CREATE и WM_DESTROY функции WinDefWindowProc .


Параметры этой функции полностью аналогичны параметрам функции окна.

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

Аналогично, в процессе уничтожения окна функции окна передается сообщение WM_DESTROY . Обработчик этого сообщения должен освободить ресурсы, заказанные у операционной системы обработчиком сообщения WM_CREATE .

Сравнивая окно с объектом языка программирования С++, можно сказать, что обработчик сообщения WM_CREATE выполняет функцию конструктора, а обработчик сообщения WM_DESTROY - функцию деструктора объекта.

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


Содержание раздела