2014-10-29 50 views
1

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

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; 

我需要将数据分配给InitNode事件中的节点,但不知道如何分配它。

+0

我可以猜到编译器错误是什么,但要说教,请问编辑问题以包含编译器错误。我其实认为你在这里有两个明显的错误。但是你最好告诉我们他们是什么。 – 2014-10-29 14:49:00

+1

'DiagData:= Sender.GetNodeData(Node); DiagData.DiagID:= ...'或'DiagData:= Sender.GetNodeData(Node); DiagData ^:= FDiagDataList.Items [c]'但什么是'c'? – TLama 2014-10-29 14:49:14

+0

@TLama:是的,它的工作原理! – 2014-10-29 14:51:44

回答

2

不要直接读写Node.Data。数据需要不一定会在该字段的地址。 (树控件有一个允许后代为自己保留额外数据的机制。)相反,请致电Sender.GetNodeData

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

您的代码会失败,因为Node.Data的类型是record;你不能用^来解引用它。在简单情况下,由GetNodeData返回的值将等于该字段的地址(即,GetNodeData(Node) = @Node.Data)。但不要以为所有情况都很简单。正如我所说,树控后裔可以保留自己的数据空间,所以你是分享该空间的代码是在你的控制之外,并且它是由树控制来管理哪个数据空间是你的。始终致电GetNodeData


此外,你对你的数据类型感到困惑。你说FDiagDataList是一个TObjectList,但你明确存储的东西不是后裔TObject。当您不使用对象时,请勿使用TObjectList。如果您使用的是版本德尔福于2009年早期,然后用TList和存储指针TDiagData

NodeData^ := PDiagData(FDiagDataList[c])^; 

如果您使用的Delphi 2009或更高版本,然后用TList<TDiagData>,然后摆脱类型转换:

NodeData^ := FDiagDataList[c]; 

无论哪种方式,你可能会发现事情变得更容易管理,如果事件处理程序开始时以同样的方式,具有GetNodeData调用获取类型安全点呃到当前节点的数据。

+0

Eeek!那'c'仍然与我们在一起。 – TLama 2014-10-29 17:03:18

+0

那么,@Tlama?我们可以用一些元表达式替换它,*'expression-that-selecting-data-for-current-node' *,但是我们也可以假设*'c' *已经*是这样一个表达式。为什么要说话? – 2014-10-29 17:18:24

+0

@RobKennedy:好,相关答案。 – 2014-10-29 17:36:06

相关问题