![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
TCustomTreeView.CreateWnd и DestroyWnd [D5, Win2k]
Ega23 © (2006-08-31 12:55:00)Можно ли как-то обойти сохранение-считывание нодов в поток?
Ega23 (2006-08-31 14:46:00) [1]
> Reindeer Moss Eater © (31.08.06 14:42) [12]
Зато теперь я полностью "прочухал" всю эту борландовскую связку TDataSet->TDataSource->TDataLink... :о)
Ega23 (2006-08-31 14:45:00) [2]
> Есть же фриварный пакет в исходниках VirtualControls c тем
> самым dbaware три вью.
Эта (моя) дрянь весьма специфична. Проще было самому писать, чем модифицировать другие.
Reindeer Moss Eater (2006-08-31 14:42:00) [3]Мда. Интересно жить не запретишь, как говорится.
Есть же фриварный пакет в исходниках VirtualControls c тем самым dbaware три вью.
Ega23 (2006-08-31 14:18:00) [4]Какое нашли решение:
На перекрытый DestroyWnd грохать список всех узлов, запомнив предварительно "карту раскрытия" (добавить в TDBTreeViewItem свойство Expanded), и уже после этого вызывать inherited DestroyWnd.
На перекрытый CreateWnd рекурсивно строить список узлов по имеющимуся списку TDBTreeViewItem'ов и восстанавливать карту раскрытия.
Ega23 (2006-08-31 14:11:00) [5]Поскольку у TCustomTreeView есть эти два дурных метода с сохранением и восстановлением узлов из потока, была выявлена проблема, что при Hide/Show парента, на котором лежит компонент, пропадала связка между TDBTreeViewItem.Node и реальным узлом (обратная, между TTreeNode.Data и TDBTreeViewItem сохранялась). Почему - понятно, узлы создаются заново и адрес их меняется.
Перекрыв метод TCustomTreeview.CreateWnd была сделана проверка связей и их восстановление от TDBTreeViewItem к узлу.
Всё было хорошо до вчерашнего дня (а может и не всё хорошо, просто выплыло вчера...)
В силу обстоятельств, на событие OnActivate фрейма (собственное событие, фактически - BeforeActivate), где лежит данное дерево, был поставлен TDataSet.Close; TDataSet.Open;, т.е. обновление набора данных.
Таким образом, получилось следующее: на destroyWnd данные о нодах сохранились в стрим, на открытие запроса список узлов очистился (а он и так был пустым, т.к. они все в стриме), были созданы экземпляры TDBTreeViewItem и узлов из набора данных, а потом был восстановлен список узлов из стрима.
Продолжение следует.
MBo (2006-08-31 14:07:00) [6]>Вопрос: нафига вообще это сохранение узлов и "карты раскрытия" в поток нужно?
Окно может пересоздаваться, например, при изменении Parent
А хранение узлов TreeView отдано Windows (как и для многих контролов, являющихся обертками над стандартными виндовыми, как, например, ListBox)
Ega23 (2006-08-31 13:57:00) [7]Сначала один вопрос, потом описание проблемы и способ реализации одного из решений, которое сейчас в курилке мозговым штурмом нашли.
Вопрос: нафига вообще это сохранение узлов и "карты раскрытия" в поток нужно?
Теперь, собственно, проблема и решение.
Делаю компонент TDBTreeView для отображения иерархических структур.
Унаследовался от TCustomTreeView, добавил свойства DataSource, KeyField, ParentField, DisplayField (Node.Text) и ещё по-мелочам.
Создал потомка TdataLink, создал класс TDBTreeViewItem
TDBTreeViewItem = class(TObject)
private
............
public
constructor Create;
destructor Destroy; override;
function isValid : boolean;
property KeyFieldValue:Variant Read FKeyFieldValue Write FKeyFieldValue;
property ParentKeyFieldValue:Variant Read FParentKeyFieldValue Write FParentKeyFieldValue;
property DisplayFieldValue:String Read FDisplayFieldValue Write FDisplayFieldValue;
property HintFieldValue : String Read FHintFieldValue Write FHintFieldValue;
property ImageIndex:Integer Read FImageIndex Write FImageIndex;
property Image:TBitmap Read FImage Write FImage;
property Node:TTreeNode Read FNode Write set_Node;
end;
При TdataSet.Open через TTreeDataLink ловлю событие ActiveChanged. По нему:
1. Очищаю список TDBTreeViewItem'ов
2. Очищаю список Nod'ов.
3. Если Active=True - запускаю процедуру, которая в цикле по TDataSet.ActiveRecord строит список TDBTreeViewItem'ов, при этом заодно ищет минимальное значение ParenField (это будет root).
4. Запускаю рекурсивную процедуру создания узлов для этого списка, при этом при создании узла в Node.Data пишу указатель на соответствующий TDBTreeViewItem, а в нём в свойство Node пишу указатель на полученный Node. Таким образом получаются 2 синхронизированных списка.
Продолжение следует.
MBo (2006-08-31 13:39:00) [8]Кстати, условие FCreateWndRestores имеет соответствующее property CreateWndRestores - так им и воспользоваться?
han_malign (2006-08-31 13:36:00) [9]эээ...
CreateWndRestores:= false;
- не катит?
MBo (2006-08-31 13:35:00) [10]В обоих методах загрузка-сохранение делается при выполнении if-ов. Можно сделать перед вызовом inherited так, чтобы условия не выполнялись (потом восстановить параметры)
P.S. Метод дедушки можно вызвать через TMethod
Ega23 (2006-08-31 13:25:00) [11]
> Но останется придумать как вызвать унаследованные методы
> от TWinContol'а
В этом-то вся проблема...
Reindeer Moss Eater (2006-08-31 13:13:00) [12]копи & пасте оба метода в потомка и там закоментарить ненужные вызовы и не вызывать inherited от TCustomTreeView.
Но останется придумать как вызвать унаследованные методы от TWinContol'а
Ega23 (2006-08-31 13:05:00) [13]Стоп. У меня потомок TCustomTreeView. Так вот я не хочу, чтобы в предке на DestroyWnd данные о нодах писАлись в поток, а на CreateWnd - читались.
Reindeer Moss Eater (2006-08-31 12:58:00) [14]так оба же виртуальные