Click here to Skip to main content
15,891,943 members
Articles / Desktop Programming / MFC

A Faster Tree Control

,
Rate me:
Please Sign up or sign in to vote.
4.69/5 (13 votes)
16 Dec 2003CPOL5 min read 394.2K   3.7K   82  
An article about an open source and free fast tree control
// TreeDlgDlg.cpp : implementation file
//

#include "stdafx.h"
#include "resource.h"
#include "TreeDlgDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTreeDlgDlg dialog

CTreeDlgDlg::CTreeDlgDlg(CWnd* pParent /*=NULL*/) : CDialog(CTreeDlgDlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTreeDlgDlg)
	//}}AFX_DATA_INIT
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CTreeDlgDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTreeDlgDlg)
	DDX_Control(pDX, IDC_TREE2, m_wndTreeCtrl2);
	DDX_Control(pDX, IDC_CHECK2, m_btnCheck2);
	DDX_Control(pDX, IDC_CHECK1, m_btnCheck1);
	DDX_Control(pDX, IDC_TREE1, m_wndTreeCtrl1);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CTreeDlgDlg, CDialog)
	//{{AFX_MSG_MAP(CTreeDlgDlg)
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_ADD, OnAdd)
	ON_BN_CLICKED(IDC_SORT, OnSort)
	ON_BN_CLICKED(IDC_REMOVE, OnRemove)
	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE1, OnEndLabelEdit)
	ON_NOTIFY(TVN_ENDLABELEDIT, IDC_TREE2, OnEndLabelEdit)
	ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_TREE2, OnBeginlabeleditTree2)
	ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE2, OnItemexpandingTree2)
	ON_NOTIFY(TVN_SELCHANGING, IDC_TREE2, OnSelchangingTree2)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTreeDlgDlg message handlers

BOOL CTreeDlgDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon
	m_btnCheck1.SetCheck(1);
	m_btnCheck2.SetCheck(0);
	((CButton*)GetDlgItem(IDC_OPTIMIZE))->SetCheck(1);
	
	return TRUE;  // return TRUE  unless you set the focus to a control
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CTreeDlgDlg::OnPaint() 
{
	if( IsIconic())
	{
		CPaintDC dc(this); // device context for painting
		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
		// Center icon in client rectangle
		CRect rect;
		GetClientRect(&rect);
		// Draw the icon
		dc.DrawIcon((rect.Width()-GetSystemMetrics(SM_CXICON)+1)/2, (rect.Height()-GetSystemMetrics(SM_CYICON)+1)/2, m_hIcon);
	}
	else		CDialog::OnPaint();
}

HCURSOR CTreeDlgDlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CTreeDlgDlg::Add( CTreeCtrl *pTree, bool bOptimize, UINT nIDTimeInsert, UINT nIDTimeSort, UINT nIDTimeRemove)
{
	char szString[100];
	const int Count1=20000, Count2=10;

	if( bOptimize)		pTree->SetRedraw(FALSE);
	DWORD t1 = GetTickCount();
	for( int i=Count1; i>=0; i--)
	{
		itoa( i, szString, 10);
		HTREEITEM hti = pTree->InsertItem( szString, TVI_ROOT, TVI_LAST);
		pTree->SetItemState( hti, TVIS_EXPANDED, TVIS_EXPANDED);
		for( int j=0; j<Count2; j++)
		{
			itoa( j, szString, 10);
			HTREEITEM hti2 = pTree->InsertItem( szString, hti, TVI_LAST);
			itoa( 0, szString, 10);
			pTree->InsertItem( szString, hti2, TVI_LAST);
		}
	}
	if( bOptimize)		pTree->SetRedraw();
	SetDlgItemInt( nIDTimeInsert, GetTickCount()-t1);
	SetDlgItemInt( nIDTimeSort, 0);
	SetDlgItemInt( nIDTimeRemove, 0);
}

void CTreeDlgDlg::OnAdd() 
{
	bool bOptimize = ((CButton*)GetDlgItem(IDC_OPTIMIZE))->GetCheck() != 0;
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT));
	
	if( m_btnCheck1.GetCheck())
		Add( &m_wndTreeCtrl1, bOptimize, IDC_TIMEINSERT1, IDC_TIMESORT1, IDC_TIMEREMOVE1);
	if( m_btnCheck2.GetCheck())
		Add( &m_wndTreeCtrl2, bOptimize, IDC_TIMEINSERT2, IDC_TIMESORT2, IDC_TIMEREMOVE2);

	SetDlgItemInt( IDC_ITEMS, m_wndTreeCtrl1.GetCount() > m_wndTreeCtrl2.GetCount() ? m_wndTreeCtrl1.GetCount() : m_wndTreeCtrl2.GetCount());
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW));
}

void CTreeDlgDlg::AddRegistryItems( CTreeCtrl* pTree, HTREEITEM hti, HKEY hKey)
{
	static char szText[256];
	DWORD dw=255, dwCount=0;
	while( RegEnumKeyEx( hKey, dwCount++, szText, &dw, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
	{
		HTREEITEM hNewItem = pTree->InsertItem( szText, hti);
		if( hNewItem)
		{
			HKEY hNewKey;
			if( RegOpenKeyEx( hKey, szText, 0, KEY_ENUMERATE_SUB_KEYS, &hNewKey) == ERROR_SUCCESS)
			{
				AddRegistryItems( pTree, hNewItem, hNewKey);
				RegCloseKey( hNewKey);
			}
			dw=255;
			pTree->Expand( hNewItem, TVE_EXPAND);
		}
	}
}

void CTreeDlgDlg::Sort( CTreeCtrl *pTree, UINT nIDTimeSort)
{
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT));
	DWORD t1 = GetTickCount();
	pTree->SortChildren( pTree->GetSelectedItem());
	SetDlgItemInt( nIDTimeSort, GetTickCount()-t1);
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW));
}

void CTreeDlgDlg::OnSort() 
{
	if( m_btnCheck1.GetCheck())		Sort( &m_wndTreeCtrl1, IDC_TIMESORT1);
	if( m_btnCheck2.GetCheck())		Sort( &m_wndTreeCtrl2, IDC_TIMESORT2);
}

void CTreeDlgDlg::Remove( CTreeCtrl *pTree, bool bOptimize, UINT nIDTimeRemove, UINT nIDTimeInsert)
{
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_WAIT));
	if( bOptimize)		pTree->SetRedraw(FALSE);
	DWORD t1 = GetTickCount();
	pTree->DeleteAllItems();
	if( bOptimize)		pTree->SetRedraw( TRUE);
	SetDlgItemInt( nIDTimeRemove, GetTickCount()-t1);
	SetCursor( AfxGetApp()->LoadStandardCursor( IDC_ARROW));
}

void CTreeDlgDlg::OnRemove()
{
	bool bOptimize = ((CButton*)GetDlgItem(IDC_OPTIMIZE))->GetCheck() != 0;
	if( m_btnCheck1.GetCheck())		Remove( &m_wndTreeCtrl1, bOptimize, IDC_TIMEREMOVE1, IDC_TIMEINSERT1);
	if(m_btnCheck2.GetCheck())		Remove( &m_wndTreeCtrl2, bOptimize, IDC_TIMEREMOVE2, IDC_TIMEINSERT2);
	SetDlgItemInt( IDC_ITEMS, 0);
}

BOOL CTreeDlgDlg::PreTranslateMessage(MSG* pMsg) 
{
	CTreeCtrl *pTree = NULL;
	if( pMsg->hwnd == m_wndTreeCtrl1.m_hWnd)				pTree = &m_wndTreeCtrl1;
	else if( pMsg->hwnd == m_wndTreeCtrl2.m_hWnd)		pTree = &m_wndTreeCtrl2;
	if( pTree)
	{
		switch( pMsg->message)	
		{
			case WM_KEYDOWN:
				switch( pMsg->wParam)
				{
					case VK_DELETE:
						DeleteSelectedItem( pTree);
						break;
				}
				break;
		}
	}
	return CDialog::PreTranslateMessage(pMsg);
}

void CTreeDlgDlg::DeleteSelectedItem(CTreeCtrl *pTree)
{
	HTREEITEM hItem = pTree->GetSelectedItem();
	//int a = pTree->GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED;
	hItem = pTree->GetNextItem(hItem, /*TVGN_NEXT*/TVGN_CHILD);
	//int b= pTree->GetItemState(hItem, TVIS_SELECTED) & TVIS_SELECTED;
	//pTree->DeleteItem( hItem);
	//pTree->SelectItem( hItem);
	//pTree->EditLabel( hItem);
	pTree->EnsureVisible( hItem);
	//int a = pTree->GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED;
	//bool bbb = pTree->Expand( hItem, TVE_TOGGLE/*TVE_COLLAPSE*/);
	//int b = pTree->GetItemState(hItem, TVIS_EXPANDED) & TVIS_EXPANDED;

	//HTREEITEM hItem = pTree->GetRootItem();
//	hItem = pTree->GetNextItem(hItem, TVGN_NEXT);
//	bool bbb = pTree->Expand( hItem, TVE_TOGGLE/*TVE_COLLAPSE*/);
	//SCROLLINFO si;
	//BOOL bbbc = pTree->GetScrollInfo(SB_VERT, &si, SIF_ALL );
}

void CTreeDlgDlg::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
	*pResult = 1;
}

void CTreeDlgDlg::OnBeginlabeleditTree2(NMHDR* pNMHDR, LRESULT* pResult) 
{
	TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	*pResult = 0;
}

void CTreeDlgDlg::OnItemexpandingTree2(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	*pResult = 0;
}

void CTreeDlgDlg::OnSelchangingTree2(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	// TODO: Add your control notification handler code here
	
	*pResult = 0;
}

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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Slovakia Slovakia
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Written By
Software Developer
Germany Germany
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions