Московский инженерно-физический институт

Вид материалаПрактикум

Содержание


Оконная функция
LRESULT CALLBACK WndProc(HWND hwnd,UINT msg
Подобный материал:
1   2   3   4   5   6   7   8   9   ...   24

Оконная функция


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

Из заголовка оконной функции

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,

WPARAM wParam,LPARAM lParam)

видно, что при активизации (функцией DispatchMessage()) она получает четыре параметра. Первый параметр (hwnd) – дескриптор окна, которому предназначено данное сообщение. Это тот самый дескриптор, который был получен нами как результат работы функции CreateWindow(). Теперь этот же дескриптор вернулся к нам из Windows в виде параметра оконной функции. Он, в частности, полезен в тех случаях, когда на базе одного класса создается несколько различающихся чем-то окон. Если класс один, то и оконная функция для всех этих окон одна; анализируя тогда параметр hwnd, программа может определить, в какое именно окно пришло сообщение. У нас окно одно, однако аргумент hwnd все же понадобится.

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

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

switch(msg) {

case WM_CREATE:

...//Обработка сообщения WM_CREATE

case WM_MOUSEMOVE:

...//Обработка сообщения WM_MOUSEMOVE

case WM_TIMER:

...//Обработка сообщения WM_TIMER

case WM_DESTROY:

...//Обработка сообщения WM_DESTROY

//и т. д. для всех возможных сообщений

}

Однако реально в любой программе, по существу, требуется обрабатывать далеко не все сообщения. Например, если программа управляется только мышью, в ней нет необходимости обрабатывать сообщения от клавиатуры; совсем не обязательно программа имеет дело с таймером и т. п. Надо еще иметь в виду, что приложение получает большое количество сообщений системного характера, например о перерисовке отдельных элементов окна, определении его размеров, изменении положения окна и т. д. Всеми этими сообщениями мы не интересуемся и, возможно, даже не умеем обрабатывать их должным образом. Для того, чтобы дать возможность программисту работать только с теми сообщениями, которые ему нужны, в Windows предусмотрена специальная функция DefWin­dow­Proc(), которая умеет правильно обрабатывать практически все сообщения Windows. Единственным сообщением, не входящим “в юрисдикцию” DefWindowProc(), является сообщение об уничтожении окна WMDESTROY. Поэтому в простейшем случае, когда мы вообще не предполагаем работать с сообщениями, оконная функция все же должна включать обработку сообщения WMDESTROY:

switch(msg) {

case WM_DESTROY:

PostQuitMessage(0);

return 0;

default:

return(DefWindowProc(hwnd,msg,wParam,lParam));

}

Такая оконная функция обеспечит обработку по умолчанию всех поступающих в главное окно сообщений. Остается выяснить, как возникает сообщение WMDESTROY и в чем должна заключаться его обработка.

Обычно приложения Windows завершают свою работу по команде пользователя. Он может щелкнуть по кнопке завершения в правом верхнем углу окна, дважды щелкнуть по маленькой пиктограмме в левом верхнем углу окна, вызвать системное меню одиночным щелчком по этой пиктограмме и выбрать пункт "Закрыть" или, наконец, ввести с клавиатуры команду Alt+F4. Во всех этих случаях Windows убирает с экрана окно приложения и посылает в приложение сообщение WMDESTROY (не в очередь приложения, а с непосредственным вызовом оконной функции).

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

Выполнив все эти завершающие действия, программа должна вызвать функцию Windows PostQuitMessage(). Эта функция генерирует сообщение Windows WMQUIT, поступающее в очередь сообщений приложения. Как уже отмечалось выше, функция Get­Mes­sage(), обнаружив в очереди приложения сообщение WM­QUIT, тут же завершается с возвратом значения FALSE. Это приводит к разрыву цикла while обработки сообщений, выполнению последнего оператора return функции WinMain() и завершению программы.