The "correct" way to destroy the nodes' Data is the OnDeletion event of the tree. This event fires whenever a node is deleted (destroyed).
procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
begin
if Node.Data <> nil then
begin
TObject(Node.Data).Free; // Assuming that the Data element that you added is a class instance (it is a pointer to begin with).
Node.Data := nil;
end;
end;
BTW, I rarely use a
for loop when running through the nodes of a tree structure because it makes me think that a tree is a linear structure which is not true. For example, both TTreeView and TTreeNode have an
Items property. Are you sure that TreeView.Items refers to ALL nodes and not just to the the items of the top-level node (like in a TMenu)? IMHO, it is much safer (and faster) to think recursively and iterate through the nodes by using the
NextSibling,
FirstChild/NextChild methods:
procedure DeleteData(ATreeView: TTreeView; ANode: TTreeNode);
begin
if ANode = nil then
exit;
// Destroy the Data.
if (ANode.Data <> nil) then
begin
TObject(ANode.Data).Free;
ANode.Data := nil;
end;
// Now delete Data in the children, grandchildren etc. of the node...
if ANode.HasChildren then
DeleteData(ATreeView, ANode.GetFirstChild);
// ... and delete Data in the siblings of the node.
ANode := ANode.GetNextSibling;
if ANode <> nil then
DeleteData(ATreeView, ANode);
end;
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
var
iTemp: Integer;
begin
DeleteData(TreeView1,TreeView1.Items.GetFirstNode);
end;