CTreeListCtrl: The easiest TreeView with columns
Environment: VC6, NT4 SP3, Comctl32.dll 4.72.3110.1
Motivation
In http://www.codeguru.com, you can find some implementations of tree controls with columns. All of this implementation have the same approach: they reimplement the drawing code for a tree view control and, of course, they have to manage the column info for each node in the tree. What's wrong with this approach ? Even if I can find it implemented in codeguru, I don't like the idea of having to reimplement the drawing stuff only because the original tree view control does not support columns, and also Microsoft changes the GUI quickly, so you will find yourself re-writing or adding new drawing characteristics to this code.
Due to my need of a tree control with columns, and without any implementation which I like it, I decided to developed my own version, and my approach was really different. Knowing some of the new characteristics of the common controls that Microsoft ships with every new IE version, I thought, Could be possible to use a listview control in report mode to simulate a tree control? The answer was: yes, you can use the "indent" property for each list view item and the state image list to simulate a tree control with columns support.
Now that you known my approach, you can download the source code and see how simple it is. This is not a tree with lots of functionality and amazing characteristics, it is only the backbone of a tree with columns implementation. Even with the reduced set of functionality, this approach lets you incorporate any technique regarding the listview control.
How to insert CTreeListCtrl into your project?
To incorporate the tree control in your project you only need to simple steps:
- Insert CTreeListCtrl.h and CTreeListCtrl.cpp into you project.
- Import the State.bmp as a resource. Give it the IDB_STATE identifier.
Now you are ready to use it.
Using the CTreeListCtrl
The current implementation offers the minimum functionality to be a "read-only" tree and the tree expects you to add the items as they will result from a "preorder" iteration to the whole tree. This means that if you have all the nodes of the tree expanded, the order in which they appear is the order in which you have to insert them. Let's see an example.
Let's say you have a Hard disk partition with two folders: Program Files, and Winnt. Under Program Files, you have tree folders: Microsoft Office, Microsoft Visual Studio and InstallShield. Under Winnt you have two folders: profiles and system32, and under the profiles folder you have the folders All Users, Administrator and Davidc. You have to insert the items in the tree as follows:
- C:\
- Program Files
- Microsoft Office
- Microsoft Visual Studio
- InstallShield
- Winnt
- profiles
- All Users
- Administrator
- system32
Now that let's see the main steps to use the tree:
- Declare a member variable (e.g. m_tree) in the parent window class.
- In the WM_CREATE or WM_INITDIALOG message function handler, create the tree window. It can also be used through DDX_Control.
- Insert as many columns as you need as you will do with a listview control.
- Set the image list for the control.
- When you have to add items to the tree, for each item you must use the function AddItem to add it (with the information of the column 0) setting its level, and then call SetItemText for each other column.
Here is the code used to create the tree you can see in the sample image.
// Step one: Window creation.
m_tree.Create
(
WS_BORDER | WS_CHILD | WS_VISIBLE | LVS_REPORT |
LVS_SINGLESEL | LVS_SHOWSELALWAYS,
CRect(12, 12, 288, 228),
this,
0x100
);
// Step two: We insert two columns: Folder name, and folder size
LVCOLUMN column;
column.mask = LVCF_FMT | LVCF_IMAGE | LVCF_TEXT | LVCF_WIDTH;
column.fmt = LVCFMT_LEFT;
column.cx = 200;
column.pszText = _T("Folder");
column.iSubItem = 0;
m_tree.InsertColumn(0, &column);
column.fmt = LVCFMT_RIGHT;
column.cx = 75;
column.pszText = _T("Size");
column.iSubItem = 1;
m_tree.InsertColumn(1, &column);
// Step three: We create and set the image list
m_il.Create(IDB_FOLDERS, 16, 1, RGB(255, 0, 255));
m_tree.SetImageList(&m_il, LVSIL_SMALL);
// Step four: we insert the tree contents.
// The information in the arrays asFolders,
// asSizes and anLevels should be obtained
// as a result of a "process": selecting a
// group of records, checking the hard disk,
// etc.
CString asFolders[] =
{
"C:", "Program Files", "Microsoft Office",
"Microsoft Visual Studio", "InstallShield",
"Winnt", "profiles", "All Users", "Administrator" ,
"system32"
};
CString asSizes[]=
{ "100", "60", "10", "20", "30", "40", "5",
"2", "1" , "35"
};
int anLevels[] = { 0, 1, 2, 2, 2, 1, 2, 3, 3, 2 };
for (int i = 0; i < sizeof(asFolders) /
sizeof(asFolders[0]); i++)
{
int iItem;
iItem = m_tree.AddItem(asFolders[i], i % 3, anLevels[i]);
m_tree.SetItemText(iItem, 1, asSizes[i]);
}
Future work
There are some characteristics that can or need to be added to the tree. At least:
Sample application
The application for which I needed this tree is a program that inspects a drive partition and shows you the size of each folder. With this information you can see which folder is eating your hard disk space and delete it -if you can (e.g. do not delete Winnt).
Here you can see a screen snapshot:
Downloads
CheckDirectorySizes application - 116 KBDownload demo project - 13.4 Kb
Download source - 3.44 Kb

Comments
CheckDirectorySizes Source Code???
Posted by Legacy on 01/23/2004 12:00amOriginally posted by: JohnK
I know this is an old thread, but did anyone ever end up getting the source for CheckDirectorySizes? I could really use it!
ReplyI don't now if this has been an issue, but...
Posted by Legacy on 10/09/2003 12:00amOriginally posted by: Youngblood
I use the TreeListCtrl has some sort of display which change the value in it constently, but I had problem with the parent node, cause if they where open or close the SetItemText method() would update different row... Fix it with a little change were you overide the SetItemText Method, here it is.
BOOL CTreeListCtrl::SetItemText
(
int nItem,
int nSubItem,
LPCTSTR lpszText
)
{
m_tree.at(nItem).m_lstCols[nSubItem] = lpszText;
//***Added Code***
LVITEM item;
item.iItem = nItem;
GetItem(&item);
BOOL bResult = TRUE;
if(item.lParam == nItem)
bResult = CListCtrl::SetItemText(nItem, nSubItem, lpszText);
//***Added Code***
return bResult;
}
Tell me what you think?
An by the way, I did the same thing to the SetState Method... It's a way to synchronise your Array of List with the Visual... Any disadvantage you think? Would it be a good thing for all methods that act directly on a precise row?
ReplyCheers
Posted by Legacy on 09/27/2003 12:00amOriginally posted by: spud
Very nice -- just what I needed. Thanks.
ReplyAny chance we can do this in C#
Posted by Legacy on 07/22/2003 12:00amOriginally posted by: Zane
Any chance someone has this in some C# code?
Thanks
ReplyCollapse problem...
Posted by Legacy on 06/17/2003 12:00amOriginally posted by: Scott R.
The control has a problem correctly collapsing the tree items. For example:
- A
+ a
+ a
- B
+ b
+ b
When the '-' for B is clicked on, the following results:
-A
-B
+ b
+ b
Also, if the items were added in the order of the B's first and then the A's, it will still display as shown above. How do I turn off the sorting and is that the cause of my problem?
Thanks,
Scott R.
P.S. I am using VC++ 6.0
Reply
Multiple select
Posted by Legacy on 06/05/2003 12:00amOriginally posted by: harvinder
Its a great work, how can I add a multiple selection to this ?
Or probably checkbox in front of the item will be good enough !!!
Please comment
ReplyRegards
HArvinder SIngh
How to Port to Windows CE ?
Posted by Legacy on 06/04/2003 12:00amOriginally posted by: Rand Batchelder
Do you have any advice on porting to Windows CE ?
Replyhow to add checkboxes to all columns but only for first column of the root items
Posted by Legacy on 04/30/2003 12:00amOriginally posted by: gurudev
hi
how to add checkboxes to all columns but only for first column of the root items
thanks
ReplyBombs when run on Win2k
Posted by Legacy on 03/12/2003 12:00amOriginally posted by: Michael
Bombed at almost the end of reading my C drive and created some sort error file and closed.
Looked nice up to that point.
ReplyGreat!. But has one bug!!
Posted by Legacy on 03/12/2003 12:00amOriginally posted by: YSLee
ReplyLoading, Please Wait ...