Node.HasChildren is used at many locations in the CustomTreeView (DoCanExpand, InternalMove, DeleteChildren, GetInternalMarkAt). Since in your solution HasChildren is valid only after painting, what if an undrawn node is processed and its HasChildren is requested (e.g. expand c:\windows\winsxs when only c:\ is open -- this will not work...!)?
I added a TShellTreeView to a form and a button to open c:\windows\winsxs in the tree:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShellTreeView1.Path := 'C:\Windows\WinSxS';
end;
When I run this program the requested folder is opened in the treeview (after some time, of course...).
Now I tried to simulate your optimization in the case when the node to be opened has not yet been painted (because this is where the node gets the HasChildren value in your optimization):
In shellctrls I commented the lines in TCustomShellTreeView.PopulateTreeNodeWithFiles which assign a value of HasChildren to the NewNode. So, the nodes do not yet know HasChildren upon creation.
Then, in TCustomTreeView.DoPaintNode, I added "Node.HasChildren" at the top - this is a simplification, but corresponds to what you want to do: Assign the HasChildren value somewhere in this procedure.
When I run the program now and click the button, the ShellTreeView opens only the folder C:\Windows - it cannot open its WinSxS subfolder because the nodes have not yet been painted.
Therefore, I am convinced that your idea must be decoupled from the painting cycle. What I try to implement next is as follows:
- Add a new NodeState, nsValidHasChildren
- When a new node is created the nsValidHasChildren is not yet included in the NodeStates, i.e. it is unknown whether the node has children.
- The setter TTreeNode.SetHasChildren addes nsValidHasChildren to the NodeStates - now it is known whether the node has children.
- The getter TTreeNode.GetHasChildren checks whether nsvalidHasChildren already has been added -- in this case it return the usual value. If it has not yet been added it causes the treeview to call a virtual funtion NodeHasChildren which fires an event OnHasChildren. The ShellTreeview overrides this method to scans the file system and looks for children. The result is stored as nsHasChildren in the NodeStates, and the nsValidHasChildren is added to signal that the HasChildren value is known now as well.
This architecture avoids setting the HasChildren value at creation of the nodes. But via the method/event the true value can determined at the first time when it is needed.
I am attaching preliminarily patched version of the related units. The side cases with hidden and non-folder objects are not yet checked.
Copy the files over the original ones (make a backup copy first!) and recompile the LCL.
With these modification the folder C:\Windows\WinSxS opens instantly.