Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

Понятие события

Понятие класса | Когда начинается работа с объектом, то он размещается в памяти. | Свойства-массивы | Для классов, связанных наследованием, существует расширенная совместимость типов (совместимы по представлению в памяти). | Перекрытие элементов класса в производных классах | Информация о типе времени выполнения программы | Атрибуты доступа к элементам объектов | Механизм вызова виртуального метода | Абстрактный виртуальный метод | Методы обработки сообщений |


Читайте также:
  1. II. Случайные события
  2. Александр Невский и события 1240 и 1242 годах
  3. Античное понятие о мелосе.
  4. Безубыточность: понятие, порядок определения, факторы изменения.
  5. Брак и семья. Семья и ее функции, понятие об ответственности родителей.
  6. В христианском учении понятие «счастье» делится на мирское и духовное
  7. В. Понятие типа кадра

Наиболее общее определение события – любое происшествие, вызванное вмешательством пользователя, поведением системы или логикой кода приложения. Событие в программе может быть связано с некоторым кодом, называемым обработчиком события и отвечающим на это происшествие. С точки зрения разработчика, событие – это имя, к которому обработчик события может быть присоединен в программе.

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

Имеется два вида событий: взаимодействие пользователя и изменение состояния. События взаимодействия пользователя почти всегда вызываются в соответствии с сообщениями Windows, указывая, что пользователь делал кое-что, поэтому компонент может ответить. События изменения состояния также могут быть сведены к сообщениям Windows.

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

События уведомления просто сообщают, что некоторое событие случилось, без предоставления информации о том, где и когда. Уведомления обычно использую тип TNotifyEvent, который имеет только один параметр – отправитель события. Специфические события отличаются от событий уведомления, и используются в тех случаях, когда хотелось бы знать, не только какое событие случилось и какой компонент его вызвал, но и получить сопутствующую дополнительную информацию. В подобных случаях необходимы обработчики, которые включают параметры для дополнительной информации. В подобных случаях нужны обработчики специфических событий.

Синтаксически события объявляются почти полностью аналогично свойствам:

Property <имя события>: <указателъ на метод>

[Read <поле события метод чтения>]

[Write <поле события\метод записи>];

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

• Все события в Delphi принято именовать: OnCreate, OnClick и т.д.

В данном случае событие и соответствующее поле имеют тип TNotifyEvent.

Таким образом, в общем случае для объявления события необходимо сделать следующее:

• определить или выбрать тип данных события (тип указателя на метод) (процедурный тип);

• объявить поле соответствующего типа для хранения значения события;

• объявить (корреспондирующий – event-dispatching method) метод, который будет вызывать обработчик события, когда оно произойдет. Представить реализацию этого метода и определить механизм его вызова;

Стандартный синтаксис для реализации метода уведомления о событии имеет следующий вид:

Procedure <имя класса>.<имя метода>[(<объявление параметров>)];

Begin

<некий код> If Assigned(<пoлe события>)

Then <поле coбытия>(Self[,<дополнительные параметры>]);

<некий код>

End;

 

 

type TNotifyEvent = procedure(Sender: TObject) of object; TControl = class(TComponent) private FOnClick: TNotifyEvent; protected procedure Click; dynamic; property OnClick: TNotifyEvent read FOnClick write FOnClick; end; procedure TControl.Click;begin if Assigned(FOnClick) then FOnClick(Self);

end;

Класс TButton наследуется от TControl и публикует свойство OnClick. Object Inspector, видя свойство процедурного типа, размещает его на странице обработчиков событий. При нажатии на кнопку класс TButton вызывает метод Click, и тот вызывает соответствующий обработчик события, если последний присвоен.

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

procedure ButtonClick (Self: TButton; Sender: TButton);begin ShowMessageFmt ('Нажата кнопка %s', [Sender.Caption]); ShowMessageFmt ('Self = %s', [Self.Name]);end; procedure AssignButtonClick (const Button: TButton);var Method: TMethod;begin Method.Code:= @ButtonClick; Method.Data:= Button; Button.OnClick:= TNotifyEvent (Method);end;

В этом случае в процедуре, предназначенной быть обработчиком события, необходимо явно описать еще один, дополнительный параметр, который и будет получать значение Self. Правильный метод его описания зависит от соглашения о связях (calling convention), используемого в процедурном типе и методе. Для модели register (которая используется для всех стандартных обработчиков и принята по умолчанию для всех процедур в Delphi) этот параметр должен идти первым, а за ним – все остальные, так, как они описаны в типе обработчика события. Для приведения типов используется специальный тип TMethod, описанный в модуле System; он представляет собой внутреннюю реализацию объектного процедурного типа.

В пользу такого подхода можно найти два аргумента. Во-первых, в этом случае мы легко можем передать в обработчик события любой параметр Self (так, в примере, мы передаем словно бы собственный метод кнопки). Во-вторых, зная действительные типы параметров, мы можем использовать их при декларации процедуры и избежать лишних приведений типов: так, в ButtonClick параметры Self и Sender определены как TButton, хотя, вообще говоря, корректней бы было описать их как TObject.

Операция @

Особым моментом, о котором необходимо упомянуть, является операция @ (взятие адреса). Вообще говоря, ее следовало бы использовать при всех операциях с процедурными типами. Так, процедуру Example из самого первого примера было бы в некотором смысле правильнее записать так:

procedure Example;var CalcFunction: TCalcFunction;begin CalcFunction:= @Add; ShowMessageFmt('CalcFunction (2, 3) = %d', [CalcFunction (2, 3)]); end;

Обратите внимание на использование операции @ в присваиваниях. Результат в этом случае будет абсолютно таким же: компилятор отслеживает операции с процедурными типами и при необходимости добавляет неявную операцию взятия адреса.

Мы могли бы написать:

if CalcFunction = Add then {... }

и тем поставить компилятор перед выбором: то ли мы хотели сравнить указатели, то ли - вызвать две функции и сравнить их результаты. В случае если бы TCalcFunction определял функцию без параметров, оба этих толкования были бы синтаксически верны. Во избежание конфликтов в таких случаях компилятор всегда использует вызов процедуры, а для сравнения указателей необходимо использовать операцию @ – то есть писать

if @CalcFunction = @Add then {... }

Как правило, использования операции @ не требуется.


Дата добавления: 2015-11-16; просмотров: 58 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Понятие ссылки на метод объекта| Ошибки и исключительные ситуации

mybiblioteka.su - 2015-2024 год. (0.007 сек.)