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

События — это свойства процедурного типа. Их название принято начинать с префикса "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.

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