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