I am not sure how to assign data to a node in a VirtualStringTree. I'm need to assign a pointer to a record object to the Node's Data property in the tree control's InitNode event. However I'm getting a 'Pointer type required' 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 the data to the node in the InitNode event, but not am sure how to assign it.
Do not read or write
Node.Data
directly. The data you need won't necessarily be exactly at the address of that field. (The tree control has a mechanism for allowing descendants to reserve additional data for themselves.) Instead, callSender.GetNodeData
.Your code fails because
Node.Data
has typerecord
; you cannot dereference it with^
. In the simple case, the value returned byGetNodeData
will be equal to the address of that field (i.e.,GetNodeData(Node) = @Node.Data
). But don't assume all cases are simple. As I said, tree-control descendants can reserve data space of their own, so you're sharing that space with code that's outside your control, and it's up to the tree control to manage which data space is yours. Always callGetNodeData
.Furthermore, you're confused about your data types. You say
FDiagDataList
is aTObjectList
, but you're clearly storing something in it that isn't a descendant ofTObject
. When you're not using objects, don't useTObjectList
. If you're using a version of Delphi earlier than 2009, then useTList
and store pointers toTDiagData
:If you're using Delphi 2009 or later, then use
TList<TDiagData>
, and then get rid of the type cast:Either way, you'll probably find things easier to manage if every event handler starts out the same way, with a call to
GetNodeData
to fetch the type-safe pointer to the current node's data.