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

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

TTreeView & OnChange [D7, XP]


mfender ©   (2006-03-06 10:05:00) 

Много искал, но что-то ничего толкового не нашёл.

Вобщем, ушнаследовал от TTreeView. С Click'ом всё получилось быстро и легко:

TmfTreeView = class(TTreeView)
 protected
   procedure Click; override;
 end;

implementation

procedure TmfTreeView.Click;
begin
 inherited Click;
 Self.ChangeDataSet;
end;


Что можно сделать, чтобы унаследовать OnChange и добавить в обработчик своё? У меня не получается. Change - не виртуальный метод, а определённое событие TTVChangedEvent.


Ega23   (2006-03-06 11:36:00) [1]

А в native-обработчике стоит

procedure TCustomTreeView.Change(Node: TTreeNode);
begin
 if Assigned(FOnChange) then FOnChange(Self, Node);
end;


Так что действительно можно переопределить Change. Только inherited не забудь поставить...


mfender   (2006-03-06 11:33:00) [2]


> Ещё раз: обработчик OnChange вызывается из динамического
> метода Change

Ок. Приму к сведению. Попробую ещё раз и так.
Спасибо.


Ega23   (2006-03-06 11:29:00) [3]


> Вот так и писал:
> procedure Change(Sender: TObject; Node: TTreeNode); override;
>
> В ответ мне - ошибка, про то, что объявление метода Change
> не похоже на оригинальный метод.


Конечно ругаться будет. Ибо:

procedure Change(Node: TTreeNode); dynamic;


begin...end   (2006-03-06 11:29:00) [4]

> mfender ©   (06.03.06 11:25) [10]

А Sender-то откуда взялся? Ещё раз: обработчик OnChange вызывается из динамического метода Change . Его можно перекрыть:

TMyTreeView = class(TCustomTreeView)
protected
 procedure Change(Node: TTreeNode); override;
end

и, кроме вызова метода родителя (а значит, и вызова обработчика OnChange) делать в нём ещё что-нибудь.


mfender   (2006-03-06 11:25:00) [5]


> Не понял. Как пробовали? Что ожидали? Что не получилось?

Вот так и писал:
procedure Change(Sender: TObject; Node: TTreeNode); override;
В ответ мне - ошибка, про то, что объявление метода Change не похоже на оригинальный метод.


begin...end   (2006-03-06 11:14:00) [6]

> mfender ©   (06.03.06 11:10) [8]

Не понял. Как пробовали? Что ожидали? Что не получилось?

Да, в [7] Change нужно в protected разместить. Забыл...


mfender   (2006-03-06 11:10:00) [7]


> Не виртуальный, но динамический. Так что проблем с перекрытием
> не вижу.

Вот именно так я и пытался, но ничего не получилось.


begin...end   (2006-03-06 11:07:00) [8]

> mfender ©   (06.03.06 10:05)
> Change - не виртуальный метод

Не виртуальный, но динамический. Так что проблем с перекрытием не вижу.

TMyTreeView = class(TCustomTreeView)
 procedure Change(Node: TTreeNode); override;
end;

procedure TMyTreeView.Change(Node: TTreeNode);
begin
 ...
 inherited;
 ...
end


mfender   (2006-03-06 11:04:00) [9]


> А ты загляни в исходники TTreeView. Это всего-лишь обёртка
> вокруг TCustomTreeView. В нём (TTReeView) никакой логики
> не зашито, только определены public, private и published
> свойства.

Заглядывал. Именно с этого я и начал. Впрочем, мысль один раз была, унаследовать от TCustomTreeView.


> Казалось бы - что проще: взять и в ран-тайме подменить эти
> обработчики своими. Но тогда, если у тебя 2 экземпляра твоего
> компонента, "смотрящие" на один и тот же НД - ты получишь
> полную ерунду, т.к. "захватит" НД последний созданный. А
> если кто-то ещё раньше этот обработчик определил?

Вот потому и решился написать свой DBTreeView. Ибо изначально я понаписал прямо в основном юните столько, что сам ничего уже не понимаю по прошествии двух месяцев.)))

Ещё раз спасибо!


Ega23   (2006-03-06 10:58:00) [10]


> Кстати, а почему наследовать лутше от TCustomTreeView?


А ты загляни в исходники TTreeView. Это всего-лишь обёртка вокруг TCustomTreeView. В нём (TTReeView) никакой логики не зашито, только определены public, private и published свойства.


> Олег, т.е. со всеми событиями так и поступать в дальнейшем?


Это если оно тебе надо.
Вот пример, так сказать, "на пальцах":
Ты пишешь свой DB-компонент. По каким-то причинам решил не пользоваться той идеологией, которую Borland предлагает (TDataSet->TDataSource->TDataLink). Имеешь на это право.
Но в таком случае тебе нужно знать следующие вещи:
1. Когда набор данных изменил свойство Active (открылся - закрылся)
2. Когда в наборе данных поменялась позиция курсора.
Есть ещё, но первых двух для начала вполне достаточно.
Теоретически, всю эту информацию ты можешь вытащить, написав обработчики TDataSet.OnScroll (или AfterScroll, точно не помню) и TDataSet.OnAfterOpen.
Казалось бы - что проще: взять и в ран-тайме подменить эти обработчики своими. Но тогда, если у тебя 2 экземпляра твоего компонента, "смотрящие" на один и тот же НД - ты получишь полную ерунду, т.к. "захватит" НД последний созданный. А если кто-то ещё раньше этот обработчик определил?
Вот для этого ты и запоминаешь указатель на предыдущий обработчик, и если он не nil - вызываешь его, а потом исполняешь собственный код. В общем, некий аналог inherited.


mfender   (2006-03-06 10:34:00) [11]

Олег, т.е. со всеми событиями так и поступать в дальнейшем?
Кстати, а почему наследовать лутше от TCustomTreeView?


mfender   (2006-03-06 10:29:00) [12]

Спасибо, Дружище!


Ega23   (2006-03-06 10:27:00) [13]

Совет: наследуйся не от TTreeView, а от TCustomTreeView.


Ega23   (2006-03-06 10:26:00) [14]


TmfTreeView = class(TTreeView)
  FTreeViewOnChange:TTVChangedEvent;
protected
  constructor Create(AOwner:TComponent);
  procedure TreeViewOnChange(Sender: TObject; Node: TTreeNode);
end;

constructor TmfTreeView.Create(AOwner:TComponent);
begin
 FTreeViewOnChange:=Self.OnChange; // Запоминаем, определён ли базовый OnChange;
 Self.OnChange:=TreeViewOnChange; // Подставляем собственный обработчик
end;

procedure TmfTreeView.TreeViewOnChange(Sender: TObject; Node: TTreeNode);
begin
 if assigned(FTreeViewOnChange) then
    FTreeViewOnChange(Sender, Node); // Если базовый был определён, то выполняем его.

 ///////  Тут уже свои навороты
end;

В целом так.


Наверх

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