Published Property OnClick;

Переопределение события изменяет только его уровень защиты и не из­меняет стандартной реакции на это событие.

• Можно переопределить корреспондирующий динамический метод с целью включения в его код действий - общих для всех экземпляров этого класса.

Для изменения стандартной реакции на события всех компонентов одно­го класса следует сделать замещение корреспондирующего защищенного ди­намического метода в классе-потомке. При этом следует вызывать унаследо­ванный обработчик. Чаще всего это рекомендуется делать в начале кода за­мещения метода, хотя могут быть случаи, когда вызывать наследуемый обра­ботчик целесообразно в конце кода. Синтаксически это может выглядеть сле­дующим образом:

Type

<имя класса>=С\&&&(<класс-предок>) Protected

Procedure <метод>;Override; // Замещение метода End;

Procedure <имя класса>.<метод>; II Реализация замещающего метода Begin

Inherited <метод>; II Вызов наследуемого обработчика дополнительный код> II Добавление новых реакций End;

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

Рассмотрим пример класса, в стандартную обработку которого добавлен код вывода даты вместо заголовка на кнопке.

Type

TTimeButton=Class(TButton) // Объявление класса-потомка Protected

Procedure Click; Override; // Замещение (переопределение) метода End;

Procedure TTimeButton.Click; // Реализация замещающего метода Begin

Inherited Click; // Выполнение стандартных действий кнопкой II После стандартных действий - вывод даты Caption:=DateTimeToStr(Now);

End;

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

Таким образом, стандартные действия всех компонентов созданного на­ми класса TTimeButton будут заключаться в "утоплении" кнопки после щелч­ка, выводе даты и времени вместо названия кнопки и вызове обработчика со­бытия, если он для кнопки будет создан или делегирован.

В заключение рассмотрения вопроса о переопределении событий следу­ет сказать следующее:

• Переопределять стандартные события Delphi с целью изменения ко­манд доступа к событию невозможно и нецелесообразно:

• Поля для хранения значений стандартных событий определены в разделе Private класса и поэтому невидимы в потомках, а для переопределения необходимо указать собы­тие с одной из команд Read или Write. Поскольку любая из этих команд требует прямого или косвенного доступа к соответствующему полю свойства, то это невозможно.

Если же объявить новое поле, то необходимо будет переопределить корреспонди­рующий метод и представить его новую реализацию. При этом необходимо будет отка-

-66-

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

• Нецелесообразно потому, что принцип использования событий существенно от­личается от использования свойств. Если исключить команду Write, то нельзя будет соз­давать обработчик событий и возможна будет только обработка события, предусмотрен­ная по умолчанию. Однако для этого достаточно переопределить корреспондирующий метод. Если исключить команду Read, то невозможно будет выполнить код обработчика события, и область использования такого события трудно подыскать.

• Переопределение стандартного события с целью изменения типа со­бытия потребует объявления в классе нового поля нужного типа, переопреде­ления корреспондирующего метода или объявление нового, а также создание их реализации. Принципиально это возможно. При этом доступ к переопре­деленному событию возможен с помощью привидения типов. Вопрос заклю­чается в целесообразности.

В качестве примера создадим новый компонент, включающий переопре­деление события OnClick, заключающееся в изменении его типа (тип TNotifyEvent заменяется на тип TMouseMoveEvent), добавлении нового поля FNewOnClick типа TMouseMoveEvent и замещении метода Click.

Type

TNewButton=Class(TButton) // Объявление нового класса Protected

FNewOnClick: TMouseMoveEvent; // Объявление нового поля Public

Procedure Click; Override; // Замещение метода Property OnClick: TMouseMoveEvent Read FNewOnClick

Write FNewOnClick; // Событие End;

Procedure TNewButton.Click; // Реализация корреспондирующего метода Begin

Inherited Click; // Включен для демонстрации приведения типа IfAssigned(FNewOnClick) Then FNewOnClick(Self, [ssAlt], 50, 50);

End;

Procedure TForml.Button !MouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer);

Begin

MessageDlgPos('Move!', mtlnformation, [mbOK], 0,X, Y);

End;

Procedure TForml.Button2Click(Sender: TObject);

Begin

ShowMessage('Click!'); // Для демонстрации приведения типа End;

Создание компонента и делегирование ему события сделаем с помощью виртуального конструктора, который активизируем при открытии формы.

-67-

Procedure TFornil.ForinCreate(Sender: TObject);

Var NewBtn: TNewButton;

Begin

NewBtn :=TNewButton.Create(Self); // Создание кнопки With NewBtn Do Begin Parent:=Self;

SetBounds(10,10, 75,25);

Name:='NewBtn';

Visible:=True;

OnClick:=Buttonl.OnMouseMove; //Новое событие TButton(NewBtn).OnClick:=Button2.0nClick; // Щелчок мыши End;

End;

Приведенный пример позволяет продемонстрировать возможность пере­определения типа события и возможность доступа к переопределенному со­бытию предка с помощью приведения типов.

После запуска программы щелкнем мышью по кнопке NewBtn, - поя­вится сообщение "Click!". Щелчок по кнопке ОК формы сообщения (MessageDIg) приведет к появлению сообщения "Move!". Это демонстрация приведения типа.

Если в виртуальном конструкторе удалить последнюю строку или/и строку Inherited Click в реализации метода TNewButton.Click, то щелчок по кнопке NewBtn сразу приведет к появлению сообщения "Move!". Это означа­ет, что событие OnClick переопределено. Уведомительное событие заменено на специализированное и использованы его параметры Х и Y для вывода со­общения.

Выводы

Итак, если подвести итог, то можно сказать следующее:

• Windows является системой ориентированной на события.

• События в Delphi принимают форму сообщений.

• В недрах Windows VCL Delphi сообщения Windows обрабатываются и преобразуются в более простую для программиста форму.

• События в программе на Delphi вызываются не только сообщениями Windows, но и внутренними процессами.

• Обработка событий в Delphi сводится к написанию для каждого ком­понента своих обработчиков.