Click here to Skip to main content
15,884,298 members
Articles / Desktop Programming / MFC

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 148.2K   4.9K   47  
Save and restore multiple tree states in your MFC applications
// ChildView.cpp : implementation of the CChildView class
//

#include "stdafx.h"
#include "TreeStateSaverDemo.h"
#include "ChildView.h"
#include "TBTreeStateMgr.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CChildView

CChildView::CChildView()
{
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView,CWnd )
	//{{AFX_MSG_MAP(CChildView)
	ON_WM_PAINT()
	ON_WM_CREATE()
	ON_WM_SIZE()
	ON_WM_DESTROY()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CChildView message handlers

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;

	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), HBRUSH(COLOR_WINDOW+1), NULL);

	return TRUE;
}

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	
	// TODO: Add your message handler code here
	
	// Do not call CWnd::OnPaint() for painting messages
}


int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CWnd ::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	
	// TODO: Add your specialized creation code here
	wnd_Splitter.CreateStatic(this, 1,4);

	// The context information is passed on from the framework
	CCreateContext *pContext = (CCreateContext*)lpCreateStruct->lpCreateParams;

	// Create two views
	CRect rect;
	GetClientRect(&rect);
	int w=rect.Width()/4;
	int h=rect.Height()/4;

	wnd_Splitter.CreateView(0,0,RUNTIME_CLASS(CTreeView),CSize(w,h), pContext);
	wnd_Splitter.CreateView(0,1,RUNTIME_CLASS(CTreeView),CSize(w,h), pContext);
	wnd_Splitter.CreateView(0,2,RUNTIME_CLASS(CTreeView),CSize(w,h), pContext);
	wnd_Splitter.CreateView(0,3,RUNTIME_CLASS(CTreeView),CSize(w,h), pContext);

	wnd_Splitter.SetColumnInfo(0,150,80);
	wnd_Splitter.SetColumnInfo(1,150,80);
	wnd_Splitter.SetColumnInfo(2,150,80);
	wnd_Splitter.SetColumnInfo(3,150,80);

	// Set the pointers ..
	wnd_Tree1= (CTreeView*) wnd_Splitter.GetPane(0,0);
	wnd_Tree2= (CTreeView*) wnd_Splitter.GetPane(0,1);
	wnd_Tree3= (CTreeView*) wnd_Splitter.GetPane(0,2);
	wnd_Tree4= (CTreeView*) wnd_Splitter.GetPane(0,3);

	// Styles
	DWORD newstyle=TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_DISABLEDRAGDROP ;
	wnd_Tree1->GetTreeCtrl().ModifyStyle(NULL,newstyle);
	wnd_Tree2->GetTreeCtrl().ModifyStyle(NULL,newstyle);
	wnd_Tree3->GetTreeCtrl().ModifyStyle(NULL,newstyle);
	wnd_Tree4->GetTreeCtrl().ModifyStyle(NULL,newstyle);
	
	ASSERT( wnd_Tree1!= NULL);
	ASSERT( wnd_Tree2!= NULL);
	ASSERT( wnd_Tree3!= NULL);
	ASSERT( wnd_Tree4!= NULL);

	LoadTree(wnd_Tree1->GetTreeCtrl());
	LoadTree(wnd_Tree2->GetTreeCtrl());
	LoadTree(wnd_Tree3->GetTreeCtrl());
//	LoadTree(wnd_Tree4->GetTreeCtrl());
	LoadGiantTree(wnd_Tree4->GetTreeCtrl());

	//Load all the control states
	TBTreeStateMgr::LoadTreeState(_T("My Tree Control 1"),&(wnd_Tree1->GetTreeCtrl()));
	TBTreeStateMgr::LoadTreeState(_T("Second Tree"),&(wnd_Tree2->GetTreeCtrl()));
	TBTreeStateMgr::LoadTreeState(_T("Bad Tree #3"),&(wnd_Tree3->GetTreeCtrl()));
	TBTreeStateMgr::LoadTreeState(_T("Huge Tree 200K"),&(wnd_Tree4->GetTreeCtrl()));

	return 0;
}

void CChildView::OnSize(UINT nType, int cx, int cy) 
{
	CWnd ::OnSize(nType, cx, cy);
	
	wnd_Splitter.MoveWindow(0,0,cx,cy);
}


void CChildView::LoadTree(CTreeCtrl & ctrl)
{
	HTREEITEM cars,movies,girls;
	static const NODEINFO_T TREEDATA[] = 
	{	
		{NULL,"Cars"},
		{NULL,"Movies"},
		{NULL,"Girls"},
		{"Cars","Electric"},
		{"Cars","Normal"},
		{"Cars","Giant Sneaker"},
		{"Electric","Honda EV"},
		{"Normal","Buick"},
		{"Normal","Mazda"},
		{"Normal","Jeep"},
		{"Normal","Toyota"},
		{"Buick","1994 Lesabre"},
		{"Buick","1989 Lesabre"},
		{"Buick","1990 Century"},
		{"Buick","1994 Riviera"},
		{"Mazda","1998 Protege"},
		{"Mazda","2002 Protege"},
		{"Mazda","Old model Protege"},
		{"Mazda","Old model Protege"},
		{"Mazda","Old model Miata"},
		{"Jeep","1997 Cherokee Sport"},
		{"Jeep","1997 Cherokee Sport"},
		{"Jeep","1997 Cherokee Sport"},
		{"Jeep","1997 Cherokee Sport"},
		{"Giant Sneaker","Ford Expedition"},
		{"Giant Sneaker","Ford Excursion [8 mpg]"},
		{"Giant Sneaker","Land Rover Discovery"},
		{"Movies","Best"},
		{"Movies","Worst"},
		{"Best","Freddy Got Fingered"},
		{"Best","Dude! Wheres my car"},
		{"Best","Planet of the apes - I"},
		{"Worst","Planet of the apes - II"},
		{"Worst","Planet of the apes - III"},
		{"Worst","Planet of the apes - IV"},
		{"Worst","Planet of the apes - V"},
		{"Worst","Planet of the apes - VI"},
		{"Girls","Hot"},
		{"Girls","Cold"},
		{"Hot","Anna Kournikova"},
		{"Cold","Rosie O Donnell"},
		{NULL,NULL},
	};

	//Load data
	cars=ctrl.InsertItem("Cars",TVI_ROOT);
	movies=ctrl.InsertItem("Movies",TVI_ROOT);
	girls=ctrl.InsertItem("Girls",TVI_ROOT);
	LoadTreeData(cars,"Cars",&TREEDATA[0],ctrl);
	LoadTreeData(movies,"Movies",&TREEDATA[0],ctrl);
	LoadTreeData(girls,"Girls",&TREEDATA[0],ctrl);

}


void CChildView::LoadTreeData(HTREEITEM hParent,
							  LPCSTR name,
							  const NODEINFO_T * pTreeData,
							  CTreeCtrl &ctrl)
{
	const NODEINFO_T * oneNode;
	HTREEITEM	 hItem;

	oneNode=pTreeData;
	while (oneNode->parentItem!=NULL||oneNode->text!=NULL)
	{
		if (oneNode->parentItem!=NULL&&!strcmp(oneNode->parentItem,name)){
			hItem=ctrl.InsertItem(oneNode->text,hParent);
			LoadTreeData(hItem,oneNode->text,pTreeData,ctrl);
		}

		++oneNode;
	}
}

void CChildView::OnDestroy() 
{
	
	//Save all the control states
	TBTreeStateMgr::SaveTreeState(_T("My Tree Control 1"),&(wnd_Tree1->GetTreeCtrl()));
	TBTreeStateMgr::SaveTreeState(_T("Second Tree"),&(wnd_Tree2->GetTreeCtrl()));
	TBTreeStateMgr::SaveTreeState(_T("Bad Tree #3"),&(wnd_Tree3->GetTreeCtrl()));
	TBTreeStateMgr::SaveTreeState(_T("Huge Tree 200K"),&(wnd_Tree4->GetTreeCtrl()));
	
	//For large tree to destroy quickly
	ULONG otc=GetTickCount();
	wnd_Tree4->GetTreeCtrl().SetRedraw(FALSE);
	wnd_Tree4->GetTreeCtrl().ShowWindow(SW_HIDE);
	wnd_Tree4->GetTreeCtrl().DeleteAllItems();
	TRACE("Deleted the large tree in %u msecs\n",GetTickCount()-otc);
	
	CWnd ::OnDestroy();

}


void CChildView::LoadGiantTree(CTreeCtrl &ctrl)
{
	// A huge tree needs to be created as below
	ctrl.ShowWindow(SW_HIDE);
	ctrl.SetRedraw(FALSE);
	PopulateLargeTree(TVI_ROOT,888,0,8,&ctrl);
	ctrl.ShowWindow(SW_SHOW);
	ctrl.SetRedraw(TRUE);

}
// Generate and populate a large tree
// Ensure top level nodes are large (at least 1000 )
void CChildView::PopulateLargeTree(HTREEITEM hParent, 
								   ULONG nChildren, 
								   ULONG nCurrDepth, 
								   ULONG nMaxDepth,
								   CTreeCtrl * pTree)
{
	const ULONG MAXITEMS = 50000;
	HTREEITEM  hChild;
	static ULONG nRandChildren;
	static TCHAR buf[32];
	static ULONG nCurrItem=0L;

	// If maxdepth stop recursion
	if(nCurrDepth>=nMaxDepth) return;

	// Add n' Children to the tree
	for (ULONG j=0;j<nChildren;j++)
	{
		//Do we need to stop now
		if(++nCurrItem>=MAXITEMS) break;

		//Make a text
		wsprintf(buf,"Item-#%u-%u",j,nCurrItem);

		//Trace every 500
		if(!(nCurrItem%2000))TRACE("%u:\t\t%s\n",nCurrItem,buf);
		
		//Insert
		hChild=pTree->InsertItem(buf,hParent);

		//Recursion
		//Random number of children required between 100-800
		nRandChildren=rand()%200;
		PopulateLargeTree(hChild,nRandChildren,nCurrDepth+1,nMaxDepth,pTree);
	}

}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


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

Comments and Discussions