将数据写入PVirtualNode而不手动设置每个字段值

时间:2011-08-05 18:47:51

标签: delphi pointers virtualtreeview tvirtualstringtree

假设我有这个节点数据记录:

Type
  PPerson = ^TPerson;
  TPerson = record
   Name: String;
   Age: Integer;
   SomeBool: Boolean;
  end;

要填充我的VirtualStringTree,我会这样做:

Procedure AddToTree(Person: TPerson);
Var
 Node: PVirtualNode;
 Data: PPerson;
Begin
 Node := VT.AddChild(nil);
 Data := VT.GetNodeData(Node);
 Data.Name := Person.Name;
 Data.Age  := Person.Age;
 Data.SomeBool := Person.SomeBool;
End;

Procedure TMyForm.MyButtonClick(Sender: TObject);
Var
 Person: TPerson;
Begin
 Person.Name := 'Jeff';
 Person.Age := 16;
 Person.SomeBool := False;
 AddToTree(Person);

End:

现在,虽然这很好用,但我想简化它,所以每当我向记录中添加新字段时,我都不会修改AddToTree方法。

所以我尝试了这个:

Procedure AddToTree(Person: TPerson);
Begin
 VT.AddChild(nil,@Person);
End;

这个编译,它似乎PVirtualNode没有获取数据,因为我的VT没有显示任何内容,并且当打破OnGetText事件时,我看到变量是空的

我做错了什么? :)

4 个答案:

答案 0 :(得分:5)

记录支持赋值运算符:

procedure AddToTree(const Person: TPerson);
var
  Node: PVirtualNode;
  Data: PPerson;
begin
  Node := VT.AddChild(nil);
  Data := VT.GetNodeData(Node);
  Data^ := Person;
end;

答案 1 :(得分:3)

您没有阅读手册:)

好的,在这种情况下,来源是手册 - 引自AddChild()来源:

  

UserData可用于将用户数据区的前4个字节设置为可以使用的初始值   在OnInitNode中也会导致触发OnFreeNode事件(如果<> nil),即使该节点还没有   “正式”初始化。

以下它并不意味着以您使用它/期望它的方式使用。

BTW为什么要复制数据?为什么没有

type
  PTreeData = ^TTreeData;
  TTreeData = record
   Data: PPerson;
  end;

并分配记录New()将它们保存在树中,然后Dispose()清除树时?

答案 2 :(得分:3)

使用记录作为数据持有者时,在VTV中存储数据的最佳方法是仅存储指向记录的指针,而记录本身则单独存储在列表/数组中。当可视组件实际上不拥有数据时,这也对应于虚拟和MVC范例。 IOW,添加记录的方案是:

  • 使用AllocMem,New,...
  • 为记录(!)分配内存
  • 填写其字段
  • 将其添加到列表/数组
  • 使用NodeData = PNewRecord
  • 将新节点添加到VTV

删除记录的方案是:

  • 从VTV删除相应的节点
  • 使用Finalize(!)完成记录,从而避免内存泄漏 重新计算的字段
  • 使用FreeMem,Dispose,...
  • 处理已分配的内存
  • 从列表/数组中删除项目

答案 3 :(得分:0)

还有一个“我在提出问题后2分钟找到答案” - 多么羞辱...... :(

无论如何,所以 - 这可以通过使用CopyMemory来完成,如下所示:

Procedure AddToTree(Person: TPerson);
Var
 Data: PPerson;
 Node: PVirtualNode;
Begin
 // add node
 Node := VT.AddChild(nil);
 // Get data of the node
 Data := VT.GetNodeData(Node);
 // Copy the Person stuff to the Node's data.
 CopyMemory(Data,@Person,SizeOf(Person));
End;