Главная » Win32 API » Оконная функция и способы передачи сообщений окнам

0

Оконная функция вызывается, когда в структуру mess попадает очередное сообщение, выбранное из входной очереди. Оконная функ­ция должна проанализировать код сообщения и обработать его. С каж­дым окном связывается своя оконная функция. В программе на С не­обходимо описать прототипы все оконных функций, так как это при­кладные функции с произвольными именами, а не системные, чьи про­тотипы описаны в WINUSER.H. Несмотря на то, что имена оконных функций произвольны, количество и типы ее параметров, а также тип возвращаемого значения в Windows жестко фиксированы. Описание оконной функции на С имеет вид:

LRESULT CALIiBACK WndProc (HWND hwnd,UINT m,

WPARAM wParam,LPARAM lParam) { switch(mess)

{ case WM_DESTROY: // если пользователь //завершил приложение PostQuitMessage(0) ; return 0; // возврат в Windows default: return(DefWindowProc(hwnd,mess,wParam,lParam)) ; // остальные сообщения обрабатываем функцией // по умолчанию

} // конец switch } // конец оконной функции

Описатель CALLBACK оконной функции эквивалентен описателю STDCALL, определяющему соглашение о связях вызывающей и вы­зываемой функций. В Win32 практически для всех функций действует соглашение, по которому параметры функции при ее вызове помеща­ются в стек в обратном порядке, т.е. в глубине стека помещается по­следний параметр, а на верхушке стека первый. Извлекает их из сте­ка сама функция, по прототипам описания заголовка функции легко вычислить количество байтов, занимаемых параметрами. Реальное ос­вобождение памяти в стеке осуществляется командой ret n.

Рассмотрим структуру оконной функции. Она получает 4 парамет­ра. Первый параметр hwnd представляет собой дескриптор окна, кото­рому предназначено данное сообщение. Этот дескриптор нужен при обработке сообщений, например, в тех случаях, если на базе одного класса окна создается несколько окон, а поскольку оконная функция является общей для класса, то анализ дескриптора окна позволит идентифицировать, в какое конкретно окно пришло сообщение.

Второй параметр m определяет код поступившего сообщения. Так как сообщений много, то по его коду определяется и выполняется кон­кретная ветвь оператора switch в теле оконной функции. Однако ре­ально в программе нужно обрабатывать не все поступающие сообще­ния. Для того чтобы программист мог включить в оконную функцию обработку только своих сообщений, в Windows предусмотрена функ­ция DefWindowProc, которая обрабатывает практически все сообще­ния, за исключением сообщения WMDESTROY об уничтожении ок­на. Поэтому в простейшем случае в оконной функции необходимо реализовать обработку только этого сообщения. Рассмотрим, как это реализуется.

Пользователь может закрыть окно различными способами, однако во всех случаях Windows генерирует сообщение WMDESTROY, ко­торое направляется не в очередь потока, а сразу передается оконной функции. При обработке WMDESTROY в оконной функции перед вызовом функции PostQuitMessage можно освободить созданные ре­сурсы, память, закрыть файлы и т.п. В простейшем случае можно вы­вести на экран предупреждающее сообщение. В минимальной оконной функции никаких действий не предусмотрено, сразу вызывается функ­ция PostQuitMessage, генерирующая сообщение WMQUIT, посту­пающее в очередь приложения. Это сообщение необходимо для того, чтобы функция GetMessage завершилась с false, прекратив тем самым цикл обработки сообщений.

Из вышеизложенного следует, что оконная функция может полу­чить сообщение как из очереди потока, так и непосредственно. Реали­зуют эти механизмы передачи соответственно API-функции PostMes-sage и SendMessage.

Функция PostMessage помещает сообщение в очередь сообщений окна с указанным дескриптором и возвращает управление. Если сооб­щение помещено в очередь, то функция возвращает TRUE, иначе FALSE. Выбрано сообщение из очереди будет в цикле обработки со­общений.

Функция SendMessage осуществляет непосредственную передачу сообщения оконной функции. Отличие SendMessage от PostMessage состоит в том, что SendMessage вызывает оконную функцию и воз­вращает управление только после обработки сообщения.

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

ли в очереди потока сообщение, используется функция PeekMessage, практически идентичная GetMessage.

PeekMessage имеет 5 параметров, первые 4 из которых совпадают с параметрами GetMessage:

-  адрес структуры mess, в которую поступает взятое из очереди со­общение;

-  дескриптор окна, чьи сообщения будут обработаны;

-  минимальный и максимальный номера фильтруемых сообщений;

-  флаг удаления сообщения, указывающий удалять ли сообщение из очереди после выборки (PMNOREMOVE оставить в очереди, РМ REMOVE удалить из очереди).

Тогда при медленной обработке событий рекомендуется вставить фрагмент:

if (PeekMessage(&mess,NULL,0,0,PM_REMOVE)) DispatchMessage(&mess);

Источник: Сучкова, Л.И. Win32 API: основы программирования: учебное пособие/ Л.И. Сучкова; АлтГТУ им. ИИ. Ползунова. -Барнаул, АлтГТУ, 2010. 138 с, ил.

По теме:

  • Комментарии