|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
Понятие событияНаиболее общее определение события – любое происшествие, вызванное вмешательством пользователя, поведением системы или логикой кода приложения. Событие в программе может быть связано с некоторым кодом, называемым обработчиком события и отвечающим на это происшествие. С точки зрения разработчика, событие – это имя, к которому обработчик события может быть присоединен в программе. Если разработчик реализовал код обработчика события, то он выполняется, когда это событие происходит. В противном случае обычно ничего не происходит. Имеется два вида событий: взаимодействие пользователя и изменение состояния. События взаимодействия пользователя почти всегда вызываются в соответствии с сообщениями 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, и тот вызывает соответствующий обработчик события, если последний присвоен. Можно также присвоить обработчику события указатель на обычную процедуру, не являющуюся методом класса. В этом случае предыдущий пример будет выглядеть так:
В этом случае в процедуре, предназначенной быть обработчиком события, необходимо явно описать еще один, дополнительный параметр, который и будет получать значение Self. Правильный метод его описания зависит от соглашения о связях (calling convention), используемого в процедурном типе и методе. Для модели register (которая используется для всех стандартных обработчиков и принята по умолчанию для всех процедур в Delphi) этот параметр должен идти первым, а за ним – все остальные, так, как они описаны в типе обработчика события. Для приведения типов используется специальный тип TMethod, описанный в модуле System; он представляет собой внутреннюю реализацию объектного процедурного типа. В пользу такого подхода можно найти два аргумента. Во-первых, в этом случае мы легко можем передать в обработчик события любой параметр Self (так, в примере, мы передаем словно бы собственный метод кнопки). Во-вторых, зная действительные типы параметров, мы можем использовать их при декларации процедуры и избежать лишних приведений типов: так, в ButtonClick параметры Self и Sender определены как TButton, хотя, вообще говоря, корректней бы было описать их как TObject. Операция @ Особым моментом, о котором необходимо упомянуть, является операция @ (взятие адреса). Вообще говоря, ее следовало бы использовать при всех операциях с процедурными типами. Так, процедуру Example из самого первого примера было бы в некотором смысле правильнее записать так:
Обратите внимание на использование операции @ в присваиваниях. Результат в этом случае будет абсолютно таким же: компилятор отслеживает операции с процедурными типами и при необходимости добавляет неявную операцию взятия адреса. Мы могли бы написать:
и тем поставить компилятор перед выбором: то ли мы хотели сравнить указатели, то ли - вызвать две функции и сравнить их результаты. В случае если бы TCalcFunction определял функцию без параметров, оба этих толкования были бы синтаксически верны. Во избежание конфликтов в таких случаях компилятор всегда использует вызов процедуры, а для сравнения указателей необходимо использовать операцию @ – то есть писать
Как правило, использования операции @ не требуется. Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.003 сек.) |