Click here to Skip to main content
15,181,193 members
Articles / Desktop Programming / MFC
Posted 21 May 2002


47 bookmarked

MFC Tree State Manager using XML

Rate me:
Please Sign up or sign in to vote.
3.10/5 (9 votes)
21 May 20024 min read
Save and restore multiple tree states in your MFC applications

Image 1


A vast majority of successful applications use the tree control to display a variety of information to the user. The tree control has become so ubiquitous that the users are very familiar with its operations. One of the common problems with the tree control is saving the state between sessions. This article presents a class TBTreeStateMgr that makes it effortless to save and restore the state of multiple trees.

What is a Tree State ?

The tree state consists of:

  • the expanded state, which nodes are expanded and which are collapsed
  • the selection state, which nodes are selected
  • the visibility state, which nodes are currently visible

Currently, the TBTreeStateMgr only stores the expanded state.


The following are the highlights of TBTreeStateMgr implementation:

  • Can handle multiple tree instances
  • Each tree instance must be assigned a unique tree ID
  • Uses XML to store/load the tree states
  • All methods in TBTreeStateMgr are declared static. This is due to the fact that a single instance of TBTreeStateMgr can handle storage of a number of tree states.
  • TBTreeStateMgr is threadsafe
  • Uses COM Structured Storage to store individual XML files

Using TBTreeStateMgr

  1. Include the following header file in your project:
    #include "TBTreeStateMgr.h"
  2. Ensure that CoInitialize or OleInitialize is called in the InitInstance function:
    // Init COM
  3. Place this code in the InitInstance function of your MFC application:
    // Initialize the TBTreeStateMgr //
  4. Place this code in the ExitInstance() function:
    // Uninitialize
  5. To save the tree state, simply call:  
    BOOL TBTreeStateMgr::SaveTreeState(LPCTSTR lpszTreeContextName,CTreeCtrl * pTreeCtrl);
    Note: This function is typically called before quitting the window. For example: by processing the WM_CLOSE message.
    //This call saves the specified tree instance. "My Tree1 View" is the name of the instance.
    TBTreeStateMgr::SaveTreeState(_T("My Tree1 View"),&wnd_TreeCtrl);
  6. To restore the tree instance to its saved state, simply call:
    BOOL TBTreeStateMgr::LoadTreeState(LPCTSTR lpszTreeContextName,CTreeCtrl * pTreeCtrl);

    Note: This function is typically called just after initializing the tree control with the data. For example: in the OnInitialUpdate() function

    //This call restores the wnd_TreeCtrl to a state stored under the name <code>"My Tree1 View"
    TBTreeStateMgr::LoadTreeState(_T("My Tree1 View"),&wnd_TreeCtrl);
  7. [OPTIONAL] Change the storage file.

    The TBTreeStateMgr by default stores the Structured Storage file in the current directory under the file name "CTLStateStg.ctss", if you want to specify a different directory or path, use the SetStorageFile(LPCTSTR lpszNewFile).

    // Change the storage file location

To reset all tree states, simply delete the "CtlStateStg.ctss" file. This file will be automatically generated if it is not found.


This section describes in short some of the implementation choices I had to make. I hope my use of XML and IStorage/IStream in this project will demonstrate how powerful these tools are. Structured Storage is in fact used by MSWord. The DOC format is actually a IStorage compatible file.

Conventional Approaches

There are many mechanisms to store and retrieve tree states. A popular approach seems to be to store the tree state in the registry. For document/view applications that use the tree control, some developers choose to store the latest tree state as part of the document. So each document will be able to restore its view to the state when it was last closed. The registry method is not secure, safe nor scalable. Most projects do not have the luxury of modifying the document file to accommodate storing the latest state. In any case, it is a bad idea to store the view state along with the document object.

Enter XML

While I was evaluating techniques to store the tree control state, I stumbled upon XML. XML is also highly tree structured. If we could somehow transfer the tree state to an XML document efficiently and back, we could have a really cool solution. The MSXML parser is highly efficient and widely available with IE5 deployments. The bulk of the code in TBTreeStateMgr is devoted to translating the tree state to XML and back. The XML DTD for this project is:

<!-- TBTreeStateMgr.dtd   --	The DTD for storing tree state -->
<!ELEMENT TreeState(ExpandedNodes)>
	<!ELEMENT ExpandedNodes(node*)>
	    <!ELEMENT node (#PCDATA)>
<!-- . . end . . -->


The next major problem was: How to store multiple trees?

If you open the CtlState.ctss using the "Docfile Viewer", we can see the following structure:

Image 2

As the above figure shows, the DOCfile stores each XML document in a separate stream. The reason for this architecture is: Any large scale application would have to deal with multiple trees (or) with multiple users view of the same tree. An application may also have trees in the views of multiple documents. For example: Each book document can have a tree view showing the table of contents. If we created a different XML Document for each tree instance, we may end up with hundreds of files. Another reassuring factor was Structured Storage is used extensively by MS in its own products (MSWord/Excel store DOC,XLS files in Structured Storage).


This can be enhanced to support storage of any state. Just change the XML DTD to add elements of your own liking. For example: this can be enhanced to save/restore state of Toolbars, Windows, Splitter Windows, List, Grid.


This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


About the Author

Vivek Rajan
Web Developer
India India
C++/MFC/Java programmer, I like to work on high performance user interface programming.

Comments and Discussions

QuestionError Pin
tupi_kasvala19-Sep-07 3:18
Membertupi_kasvala19-Sep-07 3:18 
Generalcan't run on my pc Pin
hifi14-Jan-04 20:07
Memberhifi14-Jan-04 20:07 
Generalcan't generate CTLStateStg.ctss Pin
hifi14-Jan-04 20:37
Memberhifi14-Jan-04 20:37 
Generalcant run on my system Pin
kimyc6-Apr-03 23:36
Memberkimyc6-Apr-03 23:36 
GeneralRe: cant run on my system Pin
suntiger13-May-03 19:29
Membersuntiger13-May-03 19:29 
GeneralRe: cant run on my system Pin
William huang30-Jun-03 6:32
MemberWilliam huang30-Jun-03 6:32 
GeneralGood job ! Pin
Ranjeet Chakraborty15-Oct-02 12:58
MemberRanjeet Chakraborty15-Oct-02 12:58 
QuestionWhy not just store this info in the registry? Pin
Anonymous5-Aug-02 11:21
MemberAnonymous5-Aug-02 11:21 
AnswerRe: Why not just store this info in the registry? Pin
Vivek Rajan25-Aug-02 19:19
MemberVivek Rajan25-Aug-02 19:19 
GeneralGood... but does not compile on my m/c Pin
Bandu Patil7-Jun-02 1:19
MemberBandu Patil7-Jun-02 1:19 
GeneralHad you found the solution? Pin
3-Jul-02 2:40
suss3-Jul-02 2:40 
GeneralRe: Had you found the solution? Pin
Vivek Rajan25-Aug-02 19:19
MemberVivek Rajan25-Aug-02 19:19 
GeneralWell done + a question Pin
Neville Franks23-May-02 13:16
MemberNeville Franks23-May-02 13:16 
GeneralRe: Well done + a question Pin
Vivek Rajan23-May-02 17:04
MemberVivek Rajan23-May-02 17:04 
GeneralRe: Well done + a question Pin
martinbf24-May-02 1:09
Membermartinbf24-May-02 1:09 
GeneralRe: Well done + a question Pin
Chris Maunder25-May-02 23:08
cofounderChris Maunder25-May-02 23:08 
GeneralRe: Well done + a question Pin
Neville Franks28-May-02 3:47
MemberNeville Franks28-May-02 3:47 
GeneralRe: Well done + a question Pin
Vivek Rajan25-Aug-02 19:21
MemberVivek Rajan25-Aug-02 19:21 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.