Форум: "Основная";
Текущий архив: 2002.04.25;
Скачать: [xml.tar.bz2];
ВнизГенерация событий в классе Найти похожие ветки
← →
Emstem (2002-04-12 14:05) [0]Господа, подскажите, plz - как заставить класс генерить события? Я так понимаю, что нужно присвоить адрес обработчика указателю с классе. Но как это в Паскале делается? И потом, обработчиков ведь может быть много.
← →
Anatoly Podgoretsky (2002-04-12 14:15) [1]События не генерируются, они возникают. Присвоения обработчика свойству делается с помощью операции ":=".
Обработчиков может быть много, но и свойств тоже, можно представить случай, когда количество обработчиков не равно количеству ствойств, тогда надо присваивать по мере необходимости.
Вариант
OnAlert := MyAlertHandler1;
Где в недрах
if чтото<константа then if Assigned(OnAlert) then ...
← →
Reindeer Moss Eater (2002-04-12 14:21) [2]Адрес обработчика присваивает пользователь класса а не его писатель.
Писателю класса в коде самого класса надо проверить, назначен ли обработчик, и если да, то вызвать его.
← →
Бурундук (2002-04-12 14:26) [3]TMyClass = class
private
FOnMyEvent: TMyEvent; // обработчик события
public
procedure MyEvent; // генерация события
//begin
// if Assigned(FOnMyEvent) then FOnMyEvent(...);
//end;
end;
← →
Emstem (2002-04-12 14:48) [4]Адрес обработчика присваивает пользователь класса а не его писатель.
Писателю класса в коде самого класса надо проверить, назначен ли обработчик, и если да, то вызвать его.
Это понятно. Вопрос в том, как назначить обработчик (типа как оператор += в C# для делегатов)
← →
Reindeer Moss Eater (2002-04-12 14:56) [5]>Emstem
Я не совсем понял тебя.
Ты хочешь чтобы у класса, который ты пишешь были события, или хочешь реагировать на события не твоего класса своими обработчиками?
← →
Emstem (2002-04-12 15:01) [6]Конкретно - есть класс
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;
← →
Бурундук (2002-04-12 15:07) [7]а это откуда - Tst.OnTextChanged - не вижу такого св-ва.
Вот так должно работать
Tst.OnChange := TForm1.OnTestChange;
← →
Игорь Шевченко (2002-04-12 15:08) [8]День добрый,
Tst.OnTextChanged := OnTestChange;
С уважением,
← →
Anatoly Podgoretsky (2002-04-12 15:08) [9]Tst.OnTextChanged := OnTestChange; И объявить Tst
← →
Emstem (2002-04-12 15:25) [10]Игорь Шевченко, Anatoly Podgoretsky
Блин, точно. Прошу прощения за ламерство.
А как быть, если обработчиков несколько?
← →
kull (2002-04-12 15:29) [11]2Podgoretsky
> События не генерируются, они возникают.
Вымахиваемся, да? :)
← →
Игорь Шевченко (2002-04-12 15:44) [12]День добрый, Emstem,
> А как быть, если обработчиков несколько?
Пояснить можно?
Если последовательно, то вызывать из одного другой...
С уважением,
← →
Anatoly Podgoretsky (2002-04-12 16:08) [13]kull © (12.04.02 15:29)
Ты решил вымахнуться?
← →
Emstem (2002-04-12 16:11) [14]Anatoly Podgoretsky, Reindeer Moss Eater, Бурундук, Игорь Шевченко, kull
СПА-СИ-БО!
Игорь Шевченко
Ну например, на событие в одном классе должны реагировать несколько других. На мой взгляд, не очень логично лазить из одного класса в другой и делать всё в одном обработчике.
← →
Игорь Шевченко (2002-04-12 16:34) [15]День добрый,
Определить реакцию на событие в тех классах, которые должны реагировать. Определить группу классов, которые должны реагировать. Посмотреть, как TWinControl рассылает сообщения о событиях своим Controls
С уважением,
← →
Бурундук (2002-04-12 16:43) [16]> А как быть, если обработчиков несколько?
Тут стандартная схема, в общем, не совсем подходит.
Тут возможны разные схемы.
Если заранее известно, что данное событие должно обрабатываться
несколькими независимыми обработчиками, которые не знают друг о друге - то в самом общем случае можно сделать список обработчиков
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;
Возможны и другие варианты - например, посылка пользовательского сообщения списку объектов (или же вызов предопределёного метода у этого же списка объектов, если они от одного предка) и т.д.
← →
Emstem (2002-04-12 17:51) [17]Игорь Шевченко
В общем-то, это вопрос, скорее академический, просто было интересно, во-первых, как это делать, и во-вторых, как это делать правильно.
Бурундук
Принцип ясен. Я просто думал, есть какие-то стандартные средства
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2002.04.25;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.006 c