При написании процедуры
окна Вы можете использовать макроопределение
WndMessages, указав в списке параметров
те сообщения, обработку которых наме-рены
осуществить. Тогда процедура окна примет
вид:
proc |
WndProc stdcall |
arg |
@@hWnd: dword,
@@msg: dword, @@wPar: dword,
@@lPar: dword |
WndMessages WndVector, WM_CREATE,
WM_SIZE, WM_PAINT, WM_CLOSE, WM_DESTROY
@@WM_CREATE:
; здесь обрабатываем сообщение WM_CREATE
@@WM_SIZE:
; здесь обрабатываем сообщение WM_SIZE
@@WM_PAINT:
; здесь обрабатываем сообщение WM_PAINT
@@WM_CLOSE:
; здесь обрабатываем сообщение WM_CLOSE
@@WM_DESTROY:
; здесь обрабатываем сообщение WM_DESTROY
endp WndProc |
Обработку каждого сообщения
можно завершить тремя способами:
-
вернуть значение TRUE,
для этого необходимо использовать
переход на метку @@ret_true;
-
вернуть значение FALSE,
для этого необходимо использовать
переход на метку @@ret_false;
-
перейти на обработку
по умолчанию, для этого необходимо
сделать переход на метку @@default.
Отметьте, что все перечисленные
метки определены в макро WndMessages и
Вам не следует определять их заново в
теле процедуры.
Теперь давайте разберёмся,
что происходит при вызове макроопределения
WndMessages. Вначале производится обнуление
счётчика параметров самого макроопределения
(число этих параметров может быть произвольным).
Теперь в сегменте данных создадим метку
с тем именем, которое передано в макроопределение
в качестве первого параметра. Имя метки
формируется путём конкатенации символов
@@ и названия вектора. Достигается это
за счёт использования оператора &.
Например, если передать имя TestLabel,
то название метки примет вид: @@TestLabel.
Сразу за объявлением метки вызывается
другое макроопределение MessageVector,
в которое передаются все остальные параметры,
которые должны быть ничем иным, как списком
сообщений, подлежащих обработке в процедуре
окна. Структура макроопределения MessageVector
проста и бесхитростна. Она извлекает первый
параметр и в ячейку памяти формата dword
заносит код сообщения. В следующую ячейку
памяти формата dword записывается адрес
метки обработчика, имя которой формируется
по описанному выше правилу. Счётчик сообщений
увеличивается на единицу. Далее следует
рекурсивный вызов с передачей ещё не зарегистрированных
сообщений, и так продолжается до тех пор,
пока список сообщений не будет исчерпан.
Сейчас в макроопределении
WndMessage можно начинать обработку. Теперь
существо обработки, скорее всего, будет
понятно без дополнительных пояснений.
Обработка сообщений в Windows
не является линейной, а, как правило,
представляет собой иерархию. Например,
сообщение WM_COMMAND может заключать в
себе множество сообщений поступающих от
меню и/или других управляющих элементов.
Следовательно, данную методику можно с
успехом применить и для других уровней
каскада и даже несколько упростить её.
Действительно, не в наших силах исправить
код сообщений, поступающих в процедуру
окна или диалога, но выбор последовательности
констант, назначаемых пунктам меню или
управляющим элементам (controls) остаётся
за нами. В этом случае нет нужды в дополнительном
поле, которое сохраняет код сообщения.
Тогда каждый элемент вектора будет содержать
только адрес обработчика, а найти нужный
элемент весьма просто. Из полученной константы,
пришедшей в сообщении, вычитается идентификатор
первого пункта меню или первого управляющего
элемента, это и будет номер нужного элемента
вектора. Остаётся только сделать переход
на обработчик.
Вообще тема макроопределений
весьма поучительна и обширна. Мне редко
доводится видеть грамотное использование
макросов и это досадно, поскольку с их
помощью можно сделать работу в ассемблере
значительно проще и приятнее.
|