How to assign data to node VirtualStringTree in InitNode event

I am not sure how to assign data to node in VirtualStringTree. I need to assign a pointer to a write object to the node Data property in the InitNode event of tree management. However, I get a "Required pointer type" compile-time error.

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; 

I need to assign node data in an InitNode event, but not sure how to assign it.

+1
source share
1 answer

Do not read or write Node.Data directly. The required data will not necessarily exactly match the address of this field. (The control tree has a mechanism that allows descendants to back up additional data for themselves.) Instead, call Sender.GetNodeData .

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

Your code crashes because Node.Data is of type record ; you cannot play it with ^ . In the simple case, the value returned by GetNodeData will be equal to the address of this field (i.e. GetNodeData(Node) = @Node.Data ). But do not assume that all cases are simple. As I said, the descendants who manage the tree can reserve their own data space, so you share this space with code that is out of your control and to the control tree to control which data space belongs to you. Always call GetNodeData .


In addition, you are not sure about your data types. You say that FDiagDataList is a TObjectList , but you explicitly store something in it that is not a descendant of TObject . If you are not using objects, do not use TObjectList . If you are using the Delphi version earlier than 2009, use TList and save pointers to TDiagData :

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

If you are using Delphi 2009 or later, use TList<TDiagData> , and then get rid of the cast type:

 NodeData^ := FDiagDataList[c]; 

In any case, you will probably find it easier to manage if each event handler runs the same way, with a call to GetNodeData to extract a text-safe pointer to the current node data.

+2
source

Source: https://habr.com/ru/post/1206357/


All Articles