unit FormMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Contnrs, VirtualTrees;
type
TfrmMain = class(TForm)
vstData: TVirtualStringTree;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure vstDataGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
private
{ Private declarations }
FList: TObjectList;
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
implementation
{$R *.dfm}
{ TfrmMain }
procedure TfrmMain.FormCreate(Sender: TObject);
var
i: Integer;
begin
{ Действия при создании формы / запуске приложения }
FList := TObjectList.Create;
for i := 0 to 99 do
begin
FList.Add(TStringList.Create);
TStringList(FList).Text := IntToStr(i + 1);
end;
vstData.NodeDataSize := sizeof(Pointer);
for i := 99 downto 0 do
begin
vstData.AddChild(vstData.RootNode, FList); //исп. только первые 4 байта переданного <буфера>. Остальное разве что в InitNode
end;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
{ Действия при разрушении формы / закрытии приложения }
FList.Free;
end;
procedure TfrmMain.vstDataGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
var
P: ^TStringList;
begin
P := vstData.GetNodeData(Node);
CellText := P.Text;
end;
end.
TVirtualStringTree & TList
Саму древовидную конструкцию я делаю. Ноды добавляются вот таким способом:
[highlight=delphi]
{ CurNode - это указатель на родительскую ноду в ДЕРЕВЕ, FCollection - указатель на текущую ноду в КОЛЛЕКЦИИ. }
ProductsTree.AddChild(CurNode, FCollection);
[/highlight]
Работает оно так, что создает дочернюю для CurNode ноду, и помещает в нее ссылку на ноду в коллекции. Причем у VirtualStringTree есть поле, где хранится размер ссылки, чтобы потом его нормально достать. Поэтому при создании ссылки я указываю этот размер:
[highlight=delphi]
ProductsTree.NodeDataSize := SizeOf(TNode);
[/highlight]
Далее чтобы узлам присвоить текст делаю так:
[highlight=delphi]
procedure TMainForm.ProductsTreeGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
ANode: Pointer;
begin
ANode := ProductsTree.GetNodeData(Node);
if Assigned(ANode) then
CellText := TNode(ANode).Name;
end;
[/highlight]
Вроде все правильно, но при попытке привести указатель к типу TNode - вылететает старый добрый AV. Похоже что перемудрено с указателями.
Постарался объяснить подробно, но если возникнут вопросы - готов ответить. Что то запарка...
хм, я вот так думаю, что мне придется разбираться самому, уж больно запутанный код с кучей преобразований типов, весь его выкладывать нецелесообразно.
Ну первое, что приходит в голову: а в FCollection указатели точно валидные?
Что-то ты походу перемудрил с VirtualTreeView. Насколько я помню, там все завязано на тип record, у тебя же везде используются классы. Видимо, там где-то нестыковка с ссылкой на класс и указателем на данные типа record. Кури маны по виртуалу внимательнее.
Цитата: nikitozz
Ну первое, что приходит в голову: а в FCollection указатели точно валидные?
да, нормальные там указатели.
Цитата: makbeth
Что-то ты походу перемудрил с VirtualTreeView. Насколько я помню, там все завязано на тип record, у тебя же везде используются классы. Видимо, там где-то нестыковка с ссылкой на класс и указателем на данные типа record. Кури маны по виртуалу внимательнее.
это я видел. но думал, что должно проканать и с ссылками на экземпляры классов. это ж иначе как компонент то юзать? лажа, факт. заменил на обычный TTreeView, а фигли делать.
Цитата: Washington
лажа, факт. заменил на обычный TTreeView, а фигли делать.
Ты просто не умеешь его готовить :D Там на самом деле сделано все нормально. Как ты думаешь, зачем нужен размер структуры в ноде? Чтобы выделять и освобождать память посредством New/Dispose. Как-то так...
[highlight=delphi]
type
PMyRec = ^TMyRec;
TMyRec = record
NodeData: Pointer;
end;
[/highlight]
Ну собственно NodeData - указатель на объект в коллекции. Попробую так.
Только единственный указатель облачать в структуру совершенно ни к чему :)
а как иначе? если оно только со структурой работает...
М-м-м.. А покажи мне где именно оно требует структуру?
нигде. но без рекорда не работает и все. =) когда вместо указателя на структуру даю ему указатель на объект в коллекции - получается левак. через этот указатель потом я не могу получить доступ к объекту в коллекции. вылетает АВ.
А с объектом не работает т.к. память по указателю на объект <> памяти по указателю на структуру.
И всеж я б вообще сделал без NodeData. Правда, подробностей о формировании дерева не знаю..
Впрочем, делай как тебе понятнее :)
опа. то есть надо передать не FCollection, а ^FCollection?
А ты все-равно думаешь по старому.
FCollection - указатель на объект
FCollection^ - сам объект
ANode := ProductsTree.GetNodeData(Node) - указатель на структуру размером
.NodeDataSize := SizeOf(TNode) = вообще 4. Ибо класс, объект - суть указатель.
TNode ж у тебя класс, я ничего не путаю?
TNode - да, класс. Только я все ж не могу понять тебя. Пример в виде кода хоть приведи что-ли. А то я уже запутываюсь в этих указателях, ссылках и адресах. )))
вот. я так не делаю и не советую, но примера ради..
[highlight=delphi]
procedure TMainForm.ProductsTreeGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: string);
var
ANode: ^TNode;
begin
ANode := ProductsTree.GetNodeData(Node);
if Assigned(ANode) then
CellText := ANode^.Name;
end; [/highlight]
Работает. :)
Видимо из за пробелов в знаниях по поводу операторов ^, @ и всяких указателей.