Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
[ Монахов ] Объектно-ориентированное программирование.doc
Скачиваний:
94
Добавлен:
16.08.2013
Размер:
490.5 Кб
Скачать

4.14. Специальные средства для работы с ms Windows: сообщения.

Для обработки сообщений Windows в Delphi существует механизм динамических методов, называемых сообщениями. Они должны быть описаны в классе как процедуры, имеющие один параметр, передаваемый по имени (через var). После описания заголовка через ";" должно идти зарезервированное слово message, после которого идет индекс — идентификатор сообщения. Описание параметра, передаваемого в процедуру через var, произвольно (в первоначальной версии Delphi параметр должен был описываться как переменная соответствующего для message типа : tWM_Size, tWM_Move, и т.д.):

type

tMyControl1=

class(tWinControl)

procedure WMSize(var message:tWMSize);message WM_Size;

{начальный вариант синтаксиса}

end;

tMyControl2=

class(tMyControl1)

procedure Resize(var Info);message WM_Size; {так тоже можно}

end;

В модуле Messages описаны обработчики практически всех необходимых сообщений Windows. Каждый обработчик имеет идентификатор — целочисленную константу. Например, WM_Size — идентификатор сообщения об изменении размера экранной формы, WM_Move — идентификатор сообщения о ее перемещении и т.д.

В обработчиках сообщений можно вызвать прародительский метод с использованием только одного слова inherited, без указания его имени: он находится автоматически по индексу.

Самый общий обработчик — метод DefaultHandler, описанный в классе tObject. При обработке сообщения обычно надо вызвать в конце обработчик для прародителя:

procedure MyMsgHandler(var message);message WM_command;

begin

MyProcessing; {некая процедура обработки сообщения}

inherited; {в отличии от конструктора, вызов в самом конце}

end;

При получении объектом от операционной системы Windows сообщения описанного типа (идентификация сообщений происходит автоматически по индексам) вызывается соответствующий обработчик. В описанном выше примере это MyMsgHandler.

Однако обычно нет необходимости обрабатывать сообщения Windows, так как имеется механизм делегирования событий, о котором сейчас пойдет речь.

При необходимости обработки сообщений в обработчике события (см. следующий параграф) надо вызвать метод application.processMessages.

4.15. События и их делегирование. Обработка событий.

События — это свойства процедурного типа. Их название принято начинать с префикса "on". Для описания события некого типа (как описать новый тип события будет рассказано далее) в объекте надо описать поле того же типа, что и свойство. Реально это поле служит указателем на процедуру обработчика события. Кроме того, надо описать собственно свойство:

fOnMyEvent:tMyEvent;

property OnMyEvent:tMyEvent

read fOnMyEvent

write fOnMyEvent;

Тут поле fOnMyEvent является ссылкой на процедуру, с помощью которой осуществляется обработка события. Это поле доступно по чтению и записи! Присваивание свойству значения — это присваивание полю fOnMyEvent указателя на метод, который будет вызываться при наступлении события. Чтение — это метод. Эти методы называются обработчиками событий. Если никакой обработчик не присвоен полю-указателю, то там хранится значение notAssigned.

Пример:

{-присваивание-}

application.onActivate:=MyMethod; {MyMethod — имя некой процедуры – обработчика события}

означает, что при запуске приложения будет сначала выполнена процедура MyMethod.

Возможность такого рода действий связана с тем, что указание имени процедуры, функции, массива, объекта в Delphi — это указание соответствующего адреса, а он в принципе может быть переприсвоен. Таким образом, события описываются как свойства, доступные по записи, и при выполнении условия совместимости по типам их обработчики могут быть переприсвоены (говорят, что события делегированы).

Общим для описания типа "событие" является первый параметр Sender типа tObject и ключевая фраза of object после описания типа. Ниже приведен пример задания и использования определенного пользователем типа события tMyEvent:

type

{tNotifyEvent=procedure(Sender:tObject)of object;}

{предопределенное простейшее событие}

tMyEvent=procedure(Sender:tObject;var aMyVar:tMyVar) of object;

tObj1=

class

fOnMyEvent:tMyEvent;

property onMyEvent:tMyEvent

read fOnMyEvent

write fOnMyEvent;

end;

tObj2=

class

procedure MyEventProcessing1(Sender:tObject;

var aMyVar:tMyVar);

procedure MyEventProcessing2(Sender:tObject;

var aMyVar:tMyVar);

end;

...

var aObj1:tObj1;

aObj2:tObj2;

myKey:Boolean;

begin

aObj1:=tObj1.Create;

aObj2:=tObj2.Create;

...

if MyKey

then

aObj1.onMyEvent:=aObj2.MyEventProcessing1

else

aObj1.onMyEvent:=aObj2.MyEventProcessing2;

...

end.

При делегировании можно присваивать методы других классов! Даже не являющихся потомком и прародителем! Но при этом должно быть полное соответствие списков параметров обработчиков событий со списком параметров процедурного типа события.

Соседние файлы в предмете Информатика