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.
source share