My applications in C++Builder use a VCL TTreeview with nodes of several derived TTreeNode classes. After changing the Windows Theme, the treeview somehow gets recreated, not just repainted. During the recreation the derived treenode destructors get called, but their constructors are not called. It appears the new nodes are all of the basic TTreeNode type instead of the derived types. As a result all methods and properties of the derived classes are lost in the process.
In addition, in the recreation the nodes obtain new addresses in TreeView->Items (TTreeNodes), which will become a problem if the theme change occurs during a long-time action upon a certain node ending with the creation of a child node, i.e. the child has to be added to a parent address that does not exist anymore.
Is there a way to prevent a theme change to have an effect on the TTreeView and its nodes? Or any other solution?
Correct. During
HWND
recreation, before itsHWND
is destroyed,TTreeView
saves its node data to a temporary memory stream and destroys its node objects, and then after a newHWND
becomes available, it creates new node objects and restores the saved node data into them. But, when saving and restoring that data, it has no concept of your derived classes, and so it can't persist them correctly.If all of your nodes are the same derived type, then you should be OK by simply using the
TTreeView.OnCreateNodeClass
event or overriding the virtualTTreeView.CreateNode()
method. But, if your nodes are using multiple derived types, then you are just SOL, sorry. There is simply no way for the native functionality to know which derived type to recreate for which node.Yes, because they are new objects.
What are you doing that takes so long that it spans across a window recreation at all? Don't save
TTreeNode
references to begin with, and you won't have this problem. If you need to track custom data, use theTTreeNode.Data
property instead, that is correctly persisted during window recreation.Not that I'm aware of, no.
Handle the window recreation yourself. Set the
TTreeView.CreateWndRestores
property tofalse
, and then override the virtualDestroyWnd()
method to save the node data however you want when theControlState
property has thecsRecreating
flag, and override the virtualCreateWnd()
method to restore that data as needed. For instance, you could save each node's class name, and then use that to create your derived node objects again.