Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Генерация событий в ;классе [D5]


Emstem ©   (2002-04-12 14:05:00) 

Господа, подскажите, plz - как заставить класс генерить события? Я так понимаю, что нужно присвоить адрес обработчика указателю с классе. Но как это в Паскале делается? И потом, обработчиков ведь может быть много.


Emstem   (2002-04-12 17:51:00) [1]

Игорь Шевченко
В общем-то, это вопрос, скорее академический, просто было интересно, во-первых, как это делать, и во-вторых, как это делать правильно.

Бурундук
Принцип ясен. Я просто думал, есть какие-то стандартные средства


Бурундук   (2002-04-12 16:43:00) [2]

> А как быть, если обработчиков несколько?

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

TTest = class(TObject)
private
m_Text: string;

m_OnChangeHandlers: TMethodList;
// нужен специальный список, поскольку ссылка на метод класса занимает 8 байт

function getText: string;
procedure setText(value: string);
published
constructor Create;
property Text: string read getText write setText;
//property OnChange: TNotifyEvent read m_OnChange write
m_OnChanged;
procedure AddOnChange(AOnChange: TNotifyEvent);
procedure RemoveOnChange(AOnChange: TNotifyEvent);
end;

//Генерация
procedure TTest.setText(value: string);
var i: Integer;
begin
m_Text := value;
for i := 0 to m_OnChangeHandlers.Count-1 do
TNotifyEvent(m_OnChangeHandlers[i])(self);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Tst := TTest.Create;
Tst.AddOnChange(OnTestChange);
end;

Возможны и другие варианты - например, посылка пользовательского сообщения списку объектов (или же вызов предопределёного метода у этого же списка объектов, если они от одного предка) и т.д.


Игорь Шевченко   (2002-04-12 16:34:00) [3]

День добрый,

Определить реакцию на событие в тех классах, которые должны реагировать. Определить группу классов, которые должны реагировать. Посмотреть, как TWinControl рассылает сообщения о событиях своим Controls

С уважением,


Emstem   (2002-04-12 16:11:00) [4]

Anatoly Podgoretsky, Reindeer Moss Eater, Бурундук, Игорь Шевченко, kull
СПА-СИ-БО!

Игорь Шевченко
Ну например, на событие в одном классе должны реагировать несколько других. На мой взгляд, не очень логично лазить из одного класса в другой и делать всё в одном обработчике.


Anatoly Podgoretsky   (2002-04-12 16:08:00) [5]

kull © (12.04.02 15:29)
Ты решил вымахнуться?


Игорь Шевченко   (2002-04-12 15:44:00) [6]

День добрый, Emstem,

> А как быть, если обработчиков несколько?
Пояснить можно?

Если последовательно, то вызывать из одного другой...

С уважением,


kull   (2002-04-12 15:29:00) [7]

2Podgoretsky

> События не генерируются, они возникают.


Вымахиваемся, да? :)


Emstem   (2002-04-12 15:25:00) [8]

Игорь Шевченко, Anatoly Podgoretsky
Блин, точно. Прошу прощения за ламерство.

А как быть, если обработчиков несколько?


Anatoly Podgoretsky   (2002-04-12 15:08:00) [9]

Tst.OnTextChanged := OnTestChange; И объявить Tst


Игорь Шевченко   (2002-04-12 15:08:00) [10]

День добрый,

Tst.OnTextChanged := OnTestChange;

С уважением,


Бурундук   (2002-04-12 15:07:00) [11]

а это откуда - Tst.OnTextChanged - не вижу такого св-ва.

Вот так должно работать
Tst.OnChange := TForm1.OnTestChange;


Emstem   (2002-04-12 15:01:00) [12]

Конкретно - есть класс

TTest = class(TObject)
private
m_Text: string;

m_OnChange: TNotifyEvent;

function getText: string;
procedure setText(value: string);
published
constructor Create;
property Text: string read getText write setText;
property OnChange: TNotifyEvent read m_OnChange write m_OnChanged;
end;
...
//Генерация
procedure TTest.setText(value: string);
begin
m_Text := value;
if (Assigned(m_OnChange) then
m_OnChang(self);
end;
...
//Обработчик(???)
procedure TForm1.OnTestChange(Sender: TObject);
begin
Label1.Caption := (Sender as TTest).Text;
end;
...
procedure TForm1.FormCreate(Sender: TObject);
begin
Tst := TTest.Create;

//И как это должно выглядеть?
Tst.OnTextChanged := TForm1.OnTestChange;//На это ругается
end;


Reindeer Moss Eater   (2002-04-12 14:56:00) [13]

>Emstem
Я не совсем понял тебя.
Ты хочешь чтобы у класса, который ты пишешь были события, или хочешь реагировать на события не твоего класса своими обработчиками?


Emstem   (2002-04-12 14:48:00) [14]

Адрес обработчика присваивает пользователь класса а не его писатель.
Писателю класса в коде самого класса надо проверить, назначен ли обработчик, и если да, то вызвать его.


Это понятно. Вопрос в том, как назначить обработчик (типа как оператор += в C# для делегатов)


Бурундук   (2002-04-12 14:26:00) [15]

TMyClass = class
private
FOnMyEvent: TMyEvent; // обработчик события
public
procedure MyEvent; // генерация события
//begin
// if Assigned(FOnMyEvent) then FOnMyEvent(...);
//end;
end;


Reindeer Moss Eater   (2002-04-12 14:21:00) [16]

Адрес обработчика присваивает пользователь класса а не его писатель.
Писателю класса в коде самого класса надо проверить, назначен ли обработчик, и если да, то вызвать его.


Anatoly Podgoretsky   (2002-04-12 14:15:00) [17]

События не генерируются, они возникают. Присвоения обработчика свойству делается с помощью операции ":=".
Обработчиков может быть много, но и свойств тоже, можно представить случай, когда количество обработчиков не равно количеству ствойств, тогда надо присваивать по мере необходимости.
Вариант

OnAlert := MyAlertHandler1;

Где в недрах

if чтото<константа then if Assigned(OnAlert) then ...


Наверх

Титульная страница Поиск, карта сайта Написать письмо