Delphi 如何在InitNode事件中将数据分配给VirtualStringTree的节点

Delphi 如何在InitNode事件中将数据分配给VirtualStringTree的节点,delphi,virtualtreeview,tvirtualstringtree,Delphi,Virtualtreeview,Tvirtualstringtree,我不知道如何将数据分配给VirtualStringTree中的节点。我需要在树控件的InitNode事件中为节点的数据属性分配一个指向记录对象的指针。但是,我得到了一个“需要指针类型”的编译时错误 type TDiagData = record DiagID: Integer; DiagName: String; Selected: Byte; end; PDiagData = ^TDiagData; var FDiagDataList: TObjec

我不知道如何将数据分配给VirtualStringTree中的节点。我需要在树控件的InitNode事件中为节点的数据属性分配一个指向记录对象的指针。但是,我得到了一个“需要指针类型”的编译时错误

type
  TDiagData = record
    DiagID: Integer;
    DiagName: String;
    Selected: Byte;
  end;

  PDiagData = ^TDiagData;

var
  FDiagDataList: TObjectList;
  c: Integer; // used as an iterator for the list // incremented in vst1InitNode



procedure Btn1Click;
var
  DiagData : PDiagData;
begin

  try
    FDiagDataList := TObjectList.Create; // TODO: Move this to form constructor

    for c := 1 to 10 do
    begin
      New(DiagData);

      DiagData.DiagID := c;
      DiagData.DiagName := Format('Diag# %d', [c]);

      FDiagDataList.Add(DiagData);
    end;

    c := 0;

    vst1.NodeDataSize := SizeOf(TDiagData);
    vst1.RootNodeCount := 10; // test

  finally
    //  FDiagDataList.Free;   //TODO: Move this to form destructor
  end
end;

procedure vst1InitNode(Sender: TBaseVirtualTree; ParentNode, Node: PVirtualNode;
  var InitialStates: TVirtualNodeInitStates);
var
  DiagData: PDiagData;
begin

  DiagData = TDiagData(FDiagDataList.Items[c]); // FDiagDataList is a TObjectlist

  Node.Data^ := DiagData; // <--- this is not working ..
  // The error is: Pointer type required.

  Inc(c);
end;
类型
TDiagData=记录
DiagID:整数;
DiagName:字符串;
所选:字节;
结束;
PDiagData=^TDiagData;
变量
FDiagDataList:TObjectList;
c:整数;//用作vst1InitNode中递增的列表//的迭代器
程序Btn1Click;
变量
DiagData:PDiagData;
开始
尝试
FDiagDataList:=TObjectList.Create;//TODO:将此移动到窗体构造函数
对于c:=1到10 do
开始
新的(诊断数据);
DiagData.DiagID:=c;
DiagData.DiagName:=格式('Diag#%d',[c]);
FDiagDataList.Add(DiagData);
结束;
c:=0;
vst1.NodeDataSize:=SizeOf(TDiagData);
vst1.RootNodeCount:=10;//测试
最后
//FDiagDataList.Free//TODO:将其移动到窗体析构函数
结束
结束;
过程vst1InitNode(发送方:TBaseVirtualTree;父节点,节点:PVirtualNode;
var初始状态:tVirtualNodeInitState);
变量
DiagData:PDiagData;
开始
DiagData=TDiagData(FDiagDataList.Items[c]);//FDiagDataList是一个对象列表

Node.Data^:=DiagData;// 不要直接读取或写入
节点数据。您需要的数据不一定完全位于该字段的地址。(树控件有一种允许子体为自己保留额外数据的机制。)相反,请调用
Sender.GetNodeData

var
  NodeData: PDiagData;
begin
  NodeData := Sender.GetNodeData(Node);
  NodeData^ := TDiagData(FDiagDataList.Items[c]);
end;
您的代码失败,因为
节点。数据
具有类型
记录
;不能使用
^
解除对其的引用。在简单的情况下,
GetNodeData
返回的值将等于该字段的地址(即,
GetNodeData(Node)=@Node.Data
)。但不要假设所有的情况都很简单。正如我所说的,树控件的子体可以保留自己的数据空间,因此您可以与您无法控制的代码共享该空间,并且由树控件来管理属于您的数据空间。始终调用
GetNodeData

var
  NodeData: PDiagData;
begin
  NodeData := Sender.GetNodeData(Node);
  NodeData^ := TDiagData(FDiagDataList.Items[c]);
end;

此外,您对数据类型感到困惑。你说,
FDiagDataList
是一个
TObjectList
,但你显然在其中存储了一些东西,而不是
TObject
的后代。不使用对象时,不要使用
TObjectList
。如果您使用的是早于2009年的Delphi版本,则使用
TList
并存储指向
TDiagData
的指针:

NodeData^ := PDiagData(FDiagDataList[c])^;
如果您使用的是Delphi 2009或更高版本,请使用
TList
,然后取消类型转换:

NodeData^ := FDiagDataList[c];

无论哪种方式,如果每个事件处理程序都以相同的方式启动,通过调用
GetNodeData
来获取指向当前节点数据的类型安全指针,您可能会发现事情更容易管理。

我可以猜出编译器错误是什么,但说教一下,您能否编辑问题以包含编译器错误。事实上,我认为这里有两个明显的错误。但是您最好告诉我们它们是什么。
DiagData:=Sender.GetNodeData(Node);DiagData.DiagID:=…
DiagData:=Sender.GetNodeData(节点);DiagData^:=FDiagDataList.Items[c]
但什么是
c
?@TLama:是的,它能工作!哎呀!那
c
还在我们身边。那又怎样,@Tlama?我们可以用一些元表达式替换它,
为当前节点选择数据的表达式
,但我们也可以假设
c
已经是这样一个表达式。为什么要说得更详细?@RobKennedy:回答得很好,也很贴切。@RobKennedy,我希望你能解释c在那种情况下是什么。史蒂夫,那c在现实中是什么?@RobKennedy:你为什么说“NodeData^:=FDiagDataList[c];”?它不应该是“NodeData:=FDiagDataList[c];”吗?