Click here to Skip to main content
13,900,017 members
Click here to Skip to main content
Add your own
alternative version


228 bookmarked
Posted 17 Feb 2008
Licenced CPOL

Tree Control with Columns

, 19 Mar 2008
Rate this:
Please Sign up or sign in to vote.
Tree control with columns that can be easily used in MFC application


The CColumnTreeCtrl control can be used in MFC projects where a hybrid of tree and list is needed (see the picture above).

This code is based on Michal Mecinski's control described in Multi-Column Tree View article available on This control has several improvements and bug fixes but the general idea is the same - use standard CTreeCtrl as multi-column tree body, and CHeaderCtrl as its header.

I've added owner-drawing code (thanks to VividTree - A Colorful and Picturesque Owner Drawn CTreeCtrl article from, so you can control every aspect of CColumnTreeCtrl's appearance (tree buttons, lines, background and so on). If you want to use standard drawing code - just disable owner drawing.

You can do everything you do with standard CTreeCtrl and some things related to the CListCtrl. See Using the Code for more information.


The control described in Michal Mecinski's article already has everything you need, but there were several bugs and several missing methods (from my point of view), so I've tried to improve Michal's control a little.

Here is the list of improvements:

  • The original control is CView-derived. This control is CStatic-derived that allows to use it in dialog-based applications.
  • This control has improved scroll bars. If you noticed, the original control’s scrollbars are not displayed correctly.
  • This control supports column formatting while the original control does not.
  • This control allows to define the first column’s minimum size (if you use owner-drawing you can ignore this, but if not, then you have to define the minimum width for the first column to avoid problems with appearance);
  • This control has convenient methods for adding columns and setting column text while the original one does not. I tried not to overweight the control by adding many methods, just added couple of methods that are really needed.
  • The original control used incorrect colors for tree’s selected items and ours uses default system colors.
  • This control supports owner-drawing that allows you to control every aspect of its appearance.

Control Internals

The CColumnTreeCtrl control is implemented as container for the following child controls (see the figure below):

  1. The main header (CHeaderCtrl). It contains the columns you add to the control.
  2. Additional header (CHeaderCtrl). It is used to just fill empty space when the vertical scroll bar of child tree control (3) is displayed.
  3. The custom child tree control (CTreeCtrl). This child control contains items you add, and it also provides the vertical scroller.
  4. The horizontal scroll bar (CScrollBar). It is used to scroll the control in horizontal direction.


It was a very interesting idea proposed by Michal Mecinsky - to use standard CTreeCtrl to store items and subitems and to use custom drawing to display them properly. So, for example, the first item in the figure above is stored as a single string:

"3.5\" Floppy (A:)\tRemovable\tFAT12\t1.44Mb"

The tabulation symbol '\t' is used as subitems separator.

When WM_PAINT message is processed by CTreeCtrl, it doesn't draw items by itself, but sends custom draw notifications to the parent container, so it is possible to draw subitems as we wish.

Using the Code

Linking to Your MFC Project

You can use this control in Visual C++ 2003 and higher. I tried to compile it under Visual C++ 6.0, but it seems that it has too old SDK and doesn't support common controls library ver. 6 (distributed with IE6).

Follow these simple steps to add CColumnTreeCtrl to your MFC dialog:

  1. Copy ColumnTreeCtrl.h and ColumnTreeCtrl.cpp file to your project folder. If you place these files to another place, you may encounter some problems with linking to resources, so don't do that.
  2. Copy TREEBTNS.bmp file to your res folder. This bitmap will be used to draw buttons of tree control in owner-drawn mode.
  3. Add TREEBTNS.bmp to project resources, set its name to IDB_TREEBTNS.
  4. Add Static control to your dialog.
  5. Change its id to, for example IDC_COLUMNTREE.
  6. Right-click the static and choose "Add variable..." in context menu.
  7. In the "Variable name" field, type "m_columnTree"
  8. In the header file of your dialog, Add "#include "ColumnTreeCtrl.h"" line;
  9. In the header file of your dialog, replace "CStatic m_columnTree;" to "CColumnTreeCtrl m_columnTree;";

Owner-Drawing Support

Owner-drawing is the technique when all drawing is performed by user's drawing procedure. Although it is rather difficult to paint the entire control, this gives you the opportunity to change its appearance as you wish. When owner-drawing is disabled, standard CTreeCtrl's drawing code plus additional custom drawing code is used.

What you can do without owner-drawing? The answer is everything. However, there are following benefits of owner-drawing:

  • It allows to use background image.
  • It allows not to set minimum width for the first column. In comparison, if you don't use it, you should set the minimum width for the first column by calling CColumnTreeCtrl::SetFirstColumnMinWidth(), otherwise you will have problems with control appearance.
  • In theory, you can change every aspect of the control's appearance. Of course it means you have to understand and modify control's code for that purpose.

By default, owner-drawing is disabled. To enable it, uncomment this line in CColumnTreeCtrl.h:

//#define _OWNER_DRAWN_TREE  // comment this line if you want to use 
		           //standard drawing code

Adding and Deleting Columns

You should use these methods to add/remove columns:

// Inserts new column
    int nCol,             // zero-based column index
    LPCTSTR lpszColumnHeading,     // column heading
    int nFormat=0,             // column formatting (as in CListViewCtrl)
    int nWidth=-1,             // column width
    int nSubItem=-1            // not used

// Removes existing column
    int nCol            // zero-based column index


// insert two columns
m_columnTree.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 180);
m_columnTree.InsertColumn(1, _T("Type"), LVCFMT_LEFT, 80);

// remove last column

Adding/Removing Items


HTREEITEM hParent; // parent item

// add an item
HTREEITEM hItem = m_columnTree.GetTreeCtrl().InsertItem
			( _T("3.5\" Floppy (A:)"), hParent );

// remove 

Retrieving and Setting Item Text

You should use CColumnTreeCtrl::GetItemText() and CColumnTreeCtrl::SetItemText() methods to get/set item or subitem text.

// gets item text
    HTREEITEM hItem,     // item handle
    int nSubItem        // zero-based subitem index
// sets item text
    HTREEITEM hItem,     // item handle
    int nSubItem,         // zero-based subitem index
    LPCTSTR lpszText    // pointer to text buffer


// set text for the first and the second subitems
m_columnTree.SetItemText(hRoot, 1, _T("Removable"));
m_columnTree.SetItemText(hRoot, 2, _T("FAT12"));

Setting Minimum Width for the First Column

// sets the minimum available width for the first column
    UINT uMinWidth    // min. width

Determining Which Item is Under the Mouse Cursor

You can use CColumnTreeCtrl::HitTest() method to determine which item is under the mouse cursor.

// CTVHITTESTINFO structure contains information used to determine the 
// location of a point relative to a CColumnTreeCtrl control. 
typedef struct _CTVHITTESTINFO { 
  POINT pt;   // Client coordinates of the point to test.
  UINT flags; // Standard TVHT -prefixed flags.
  HTREEITEM hItem; // Handle to the item that occupies the point.
  int iSubItem;    // Zero-based subitem index. 

// Call this function to determine the location of the specified point 
// relative to the client area of a CColumnTreeCtrl control.
  CPoint pt, 
  UINT* pFlags
  ) const;
  ) const;


// NM_RCLICK notification handler
void CMainDlg::OnRclickedColumntree(LPNMHDR pNMHDR, LRESULT* pResult)
  CPoint pt;


  CTVHITTESTINFO htinfo; = pt;
  HTREEITEM hItem = m_columnTree.HitTest(&htinfo);

    CString szState;
    szState += _T("Clicked on item's button.");
    // ... check other flags

    CString szItemText = m_columnTree.GetItemText(hItem, htinfo.iSubItem);
    MessageBox(szState + _T(" Item text: ") + szItemText);

Accessing Child CTreeCtrl and CHeaderCtrl

You can access child tree control and header control and call their methods as usual:

// returns reference to the child tree ctrl

// returns reference to the child header ctrl


// modify style of child tree control to enable lines
m_columnTree.GetTreeCtrl().ModifyStyle(TVS_HASLINES, 0);

Setting Background Bitmap

If owner-drawing is enabled, you can specify what background bitmap to use. Standard LVBKIMAGE structure is used to store background bitmap parameters.

// gets background image
    LVBKIMAGE* plvbkImage    // structure describing image and its position
    ) const;

// sets background image
    LVBKIMAGE* plvbkImage    // structure describing image and its position


bk.xOffsetPercent = bk.yOffsetPercent = 70;
bk.hbm = LoadBitmap(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BKGND));

Processing Child Tree and Header Notifications

You can easily process notifications from the child tree and header controls in your dialog's message map, because all notifications are forwarded to the parent.


//.. fragment of the message map

//.. notify handler
void CMainDlg::OnTreeClk(NMHDR *pNMHDR, LRESULT *pResult)

    // which item was selected?
    HTREEITEM hItem = m_columnTree.GetTreeCtrl().GetSelectedItem();
    if(!hItem) return;

    // the rest of processing code..


  • February, 18 2008 - v.1.0 submitted
  • March, 24 2008 - v.1.1 submitted
    • Added CColumnTreeCtrl::HitTest() method

Known Issues

These issues were reported so far:

  • There is a problem with tooltips for now, so TVS_NOTOOLTIPS style is enabled for child tree control. Do not disable this style, or invalid tip will be displayed.
  • In the demo, when you check/uncheck some options that result in style modifications, control appearance may become incorrect. For example, vertical lines may become missing and so on. This is the problem in this demo, but this won't be a real problem in your project, because you usually won't change control's style on fly.
  • Under Windows Vista, vertical lines are drawn non-uniformly. That is not a very serious problem.
  • Horizontal scroll bar is sometimes placed incorrectly when resizing control.

Report a Bug

I hope this control will be useful, but if you find a bug, please let me know. You can post a message to the discussion thread below or email me: Please do not forget to specify how I can reproduce the incorrect behavior of control, describe what you were doing when incorrect behavior occurred, specify your Windows version and your current desktop theme.


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


About the Author

Oleg Krivtsov
Software Developer
Russian Federation Russian Federation
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralRe: What about tri-state? And notifying children and parents? Pin
RobertM8-Dec-14 5:11
memberRobertM8-Dec-14 5:11 
GeneralTooltip and Multiple Row Selection Pin
navinkaus26-May-09 23:55
membernavinkaus26-May-09 23:55 
GeneralASP.Net version Pin
Jim Brooks7-Feb-09 11:18
memberJim Brooks7-Feb-09 11:18 
QuestionHow to set bold style to htreeitem??? Pin
Michele Pelissero30-Jan-09 5:25
memberMichele Pelissero30-Jan-09 5:25 
GeneralSmall bug report. Pin
jeckle11-Jan-09 6:41
memberjeckle11-Jan-09 6:41 
GeneralRe: Small bug report. Pin
irrial6-Jul-10 15:35
memberirrial6-Jul-10 15:35 
QuestionGrid Lines Pin
BugMeNot ACCOUNT4-Jan-09 17:29
memberBugMeNot ACCOUNT4-Jan-09 17:29 
GeneralCrashing on creat Pin
Bzepp18-Dec-08 18:53
memberBzepp18-Dec-08 18:53 
TreeCtrl Crashing on creat in Initialize
Passed down CWnd* pParentWnd and used it in place of , this, and it worked.

Using SDI view not dialog.
GeneralRe: Crashing on creat Pin
Babeshade11-Mar-09 21:16
memberBabeshade11-Mar-09 21:16 
GeneralRe: Crashing on creat Pin
infiro16-Jun-10 13:28
memberinfiro16-Jun-10 13:28 
GeneralRe: Crashing on creat Pin
Ramunas_21-Oct-13 2:26
memberRamunas_21-Oct-13 2:26 
Questionhow to set image on CHeaderCtrl? Pin
lizehui14-Nov-08 17:33
memberlizehui14-Nov-08 17:33 
AnswerRe: how to set image on CHeaderCtrl? Pin
Member 76972644-Mar-11 6:33
memberMember 76972644-Mar-11 6:33 
QuestionMulti-select of items? Pin
skowald5-Nov-08 9:32
memberskowald5-Nov-08 9:32 
AnswerRe: Multi-select of items? Pin
Oleg Krivtsov5-Nov-08 17:03
memberOleg Krivtsov5-Nov-08 17:03 
GeneralRe: Multi-select of items? Pin
Manoj Panja7-Nov-12 22:51
professionalManoj Panja7-Nov-12 22:51 
QuestionHow can I change Font? Pin
kimchi8-Oct-08 19:28
memberkimchi8-Oct-08 19:28 
AnswerRe: How can I change Font? Pin
Oleg Krivtsov8-Oct-08 19:33
memberOleg Krivtsov8-Oct-08 19:33 
Questionhow to change column width dynamicly? Pin
mwxkingboy8-Sep-08 0:25
membermwxkingboy8-Sep-08 0:25 
AnswerRe: how to change column width dynamicly? Pin
Oleg Krivtsov8-Sep-08 0:30
memberOleg Krivtsov8-Sep-08 0:30 
GeneralRe: how to change column width dynamicly? Pin
mwxkingboy8-Sep-08 19:59
membermwxkingboy8-Sep-08 19:59 
GeneralRe: how to change column width dynamicly? Pin
QuiOui28-Jan-09 19:59
memberQuiOui28-Jan-09 19:59 
GeneralRe: how to change column width dynamicly? Pin
peter_mo29-Jun-09 2:33
memberpeter_mo29-Jun-09 2:33 
GeneralRe: how to change column width dynamicly? Pin
Oleg Krivtsov29-Jun-09 17:33
memberOleg Krivtsov29-Jun-09 17:33 
GeneralRe: how to change column width dynamicly? Pin
peter_mo30-Jun-09 4:54
memberpeter_mo30-Jun-09 4:54 

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.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.190306.1 | Last Updated 20 Mar 2008
Article Copyright 2008 by Oleg Krivtsov
Everything else Copyright © CodeProject, 1999-2019
Layout: fixed | fluid