Обработка сообщений в оконной функции
Оконная функция призвана организовать адекватную реакцию со стороны Win-
dows-приложения на действия пользователя и поддерживать в актуальном состо-
янии то окно приложения, сообщения которого она обрабатывает. Приложение
может иметь несколько оконных функций. Их количество определяется количе-
ством классов окон, зарегистрированных в системе функцией Register
Если
Каркасное Windows-приложение на ассемблере 399
вы помните, функции
посредством экземпляра структуры
передается указатель на определенную оконную функцию Windows-приложения.
Данная функция до конца работы приложения связана с экземплярами окон, ко-
торые, в свою очередь, создаются другой функцией API —
Когда для окна Windows-приложения появляется сообщение, операционная
система Windows производит вызов соответствующей оконной функции. Ранее
мы для упрощения говорили, что единственный источник появления сообщений —
очередь сообщений приложения, но это не совсем так. Дело в том, что сообщения,
в зависимости от источника их появления в оконной функции, могут быть двух
типов: синхронные и асинхронные. К синхронным сообщениям относятся те сооб-
щения, которые помещаются в очередь сообщений приложения и терпеливо ждут
момента, когда они будут выбраны функцией
После этого поступив-
шие сообщения попадают в оконную функцию, где и производится их обработка.
Асинхронные сообщения подобно пожарной машине попадают в оконную функ-
цию в экстренном порядке, минуя все очереди. Асинхронные сообщения, в частно-
сти, инициируются некоторыми функциями Win32 API, такими как
dow(Ex) или UpdateWIndow. Координацию синхронных и асинхронных сообщений
осуществляет Windows. Если рассматривать синхронное сообщение, то его извлече-
ние производится функцией GetMessage с последующей передачей обратно
в Windows функцией Dispatch Message. Асинхронное сообщение, независимо от ис-
точника, который инициирует его появление, сначала попадает в Windows и за-
тем — в нужную оконную функцию.
Для
реализуется именно такая схема, неужели функции Dispatch Message
нельзя сразу передать сообщение в оконную функцию? Если бы это было так,
в системе появилось бы единственное приложение-монополист, которое захвати-
ло бы все процессорное время своим циклом обработки сообщений. В схеме, реа-
лизованной в Windows, обработка сообщений приложением проводится в два эта-
па: на первом этапе приложение выбирает сообщение из очереди и отправляет его
обратно во внутренние структуры Windows; на втором этапе Windows вызывает
нужную оконную функцию приложения, передавая ей параметры сообщения. Пре-
имущество этой схемы в том, что Windows самостоятельно решает все вопросы
организации эффективной работы приложений.
Таким образом, при поступлении сообщения Windows вызывает оконную функ-
цию и передает ей ряд параметров. Все они берутся из соответствующих полей
сообщения. В нотации языка C/C++ заголовок оконной функции описан следую-
щим образом (см. листинг 16.1):
CALLBACK
(HWND
message,
wParam,
LPARAH
Здесь hWnd — дескриптор окна, которому предназначено сообщение; message —
идентификатор сообщения, характеризующий тип
wParam и IParam —
дополнительные параметры, являющиеся копиями соответствующих полей струк-
туры поступившего сообщения.
Оставшиеся два поля структуры MSG: time и POINT — используются довольно
редко, и при необходимости их значения можно извлечь непосредственно из эк-
земпляра структуры сообщения.
400 Глава
Создание Windows-приложений на ассемблере
В нашем примере Windows-приложения строки 164-167 обозначают начало
оконной функции. Параметры этой функции Windows помещает в стек. Чтобы
можно было работать с ними, используя символические имена, после заголовка
функции поместим директиву ARG (см. главу 15).
Windows требует, чтобы оконная функция сохраняла значения регистров EBI,
EDI и ESI. Причина — оконная функция должна быть рекурсивной. Например, воз-
ситуация, когда несколько классов окон применяют одну и ту же оконную
функцию для обработки сообщений, поступающих в созданные на базе этих клас-
сов окна. Имеет смысл сохранять не только
регистры, используемые
самой системой Windows, но и другие (за исключением ЕАХ), если они задей-
ствованы в оконной функции. Исходя из требования
все пе-
ременные, используемые в оконной функции, должны быть локальными. Чтобы
удовлетворить требование сохранения регистров, лучше применить (строка 166
листинга 16.4) соответствующее средство транслятора ассемблера — директиву USES
(см. также главы 10 и 15). При этом транслятор вставляет в начало и конец окон-
ной функции соответствующую последовательность команд ассемблера PUSH. Вы
можете убедиться в этом, посмотрев файл листинга (файл
программы из лис-
тинга
после ее трансляции.
Центральным местом оконной функции является синтаксическая конструкция,
в задачу которой входит распознавание поступившего сообщения
его типу
message) и передача управления на ту
кода оконной
ко-
торая продолжает далее работу с параметрами сообщения. В языке C/C++ (см.
листинг
для этого используется оператор switch (переключатель). В языке
ассемблера такого средства нет, поэтому его приходиться моделировать (см. гла-
ву 11). В листинге 16.4 строки 168-174 показывают, как это можно сделать с по-
мощью команды СМР, а также команд условного
и безусловного
переходов.
Соответствие символических имен константам, обозначающим тип сообщений
Windows, приведено во включаемом файле
Совершенно необязатель-
но анализировать типы всех возможных
параметры которых переда-
ются в оконную функцию. Структуру, подобную строкам
и вообще струк-
туру всей оконной функции можно сравнить с ситом, а сообщения — с зернами
разной величины. Отверстия в сите непростые — каждое из них пропускает зерно
своего размера. Зерна (сообщения) в сите (оконной функции) не задерживаются,
попав в него, они через одно из отверстий обязательно уходят. Уходят куда? Это
опять-таки определяется особой структурой нашего сита. Представьте, что к каж-
дому отверстию припаяна трубка, которая определяет, куда данное
по-
падет для дальнейшей обработки. Таким образом, каждому сообщению, попадаю-
щему в оконную функцию, соответствует ветвь в коде процедуры, которая начинает
обработку этого сообщения. В ходе этой обработки, возможно, понадобится вызов
других функций или применение синтаксических конструкций, подобных описан-
ному ситу, для дальнейшей более тонкой селекции сообщений, но уже одного типа
(по полям
или wParam). Для наглядности аналогию структуры оконной функ-
ции с ситом можно упрощенно представить в виде схемы (рис.
Представленная схема показывает, что оконная функция, обрабатывающая со-
общения, имеет одну точку входа и множество точек выхода. Выход осуществля-
ется из той ветви оконной функции, где обрабатывалось сообщение. Сообщения,
Средства
для разработки Windows-приложений
Среда Windows
остальные
-
.wParam
Среда Windows
0
Рис.
Абстрактное представление структуры оконной функции Windows
для которых не предусмотрена отдельная обработка, должны обрабатываться функ-
цией
(строки
Эта процедура по отношению к переданным
ей сообщениям предпринимает действия по умолчанию. В принципе, ей можно
передавать на обработку все сообщения, что в контексте рассмотренной ранее аб-
стракции означает сито, содержащее одно
в которое проваливаются все
поступающие сообщения.
По завершении работы оконная функция формирует значение в регистре ЕАХ.
Если сообщение обрабатывалось в оконной функции, то в ЕАХ необходимо помес-
тить нулевое значение. Если обработка осуществлялась по умолчанию, то есть
функцией DefWindowProc, то в ЕАХ уже сформировано возвращаемое значение,
и именно его нужно возвратить в качестве результата работы оконной функции.
В нашем примере оконная функция обрабатывает три сообщения: создание окна
WM_CREATE, перерисовку области окна WM_PAINT, закрытие окна
Более подробно с условиями возникновения и обработкой этих и других сооб-
щений можно познакомиться в литературе по Windows, где эти вопросы освеще-
ны более полно.
Do'stlaringiz bilan baham: |