CTreeListCtrl: The easiest TreeView with columns

Sample Image

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:

  1. Insert CTreeListCtrl.h and CTreeListCtrl.cpp into you project.
  2. 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:

  1. C:\
  2. Program Files
  3. Microsoft Office
  4. Microsoft Visual Studio
  5. InstallShield
  6. Winnt
  7. profiles
  8. All Users
  9. Administrator
  10. system32

Now that let's see the main steps to use the tree:

  1. Declare a member variable (e.g. m_tree) in the parent window class.
  2. In the WM_CREATE or WM_INITDIALOG message function handler, create the tree window. It can also be used through DDX_Control.
  3. Insert as many columns as you need as you will do with a listview control.
  4. Set the image list for the control.
  5. 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:

  • Reimplement DeleteItem to delete the node and its sons.
  • Support for inserting items at any position.
  • 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:


    Sample Image
    Click here for larger image

    Downloads

    CheckDirectorySizes application - 116 KB
    Download demo project - 13.4 Kb
    Download source - 3.44 Kb


    Comments

    • CheckDirectorySizes Source Code???

      Posted by Legacy on 01/23/2004 12:00am

      Originally 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!

      Reply
    • I don't now if this has been an issue, but...

      Posted by Legacy on 10/09/2003 12:00am

      Originally 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?

      Reply
    • Cheers

      Posted by Legacy on 09/27/2003 12:00am

      Originally posted by: spud

      Very nice -- just what I needed. Thanks.

      Reply
    • Any chance we can do this in C#

      Posted by Legacy on 07/22/2003 12:00am

      Originally posted by: Zane

      Any chance someone has this in some C# code?

      Thanks

      Reply
    • Collapse problem...

      Posted by Legacy on 06/17/2003 12:00am

      Originally 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:00am

      Originally 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
      Regards
      HArvinder SIngh

      Reply
    • How to Port to Windows CE ?

      Posted by Legacy on 06/04/2003 12:00am

      Originally posted by: Rand Batchelder

      Do you have any advice on porting to Windows CE ?

      Reply
    • how to add checkboxes to all columns but only for first column of the root items

      Posted by Legacy on 04/30/2003 12:00am

      Originally posted by: gurudev

      hi

      how to add checkboxes to all columns but only for first column of the root items

      thanks

      Reply
    • Great!. But has one bug!!

      Posted by Legacy on 03/12/2003 12:00am

      Originally posted by: YSLee

      <pre>
      
      Greate useful your control, if except one bug

      Ex)
      Folder size
      C:\ 100
      -> ProgramFiles 60
      D:\ <-- Not displayed
      -> Winnt 150

      How to correct this bug?
      </pre>


      Reply
    • Bombs when run on Win2k

      Posted by Legacy on 03/12/2003 12:00am

      Originally 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.

      Reply
    • Loading, Please Wait ...

    Leave a Comment
    • Your email address will not be published. All fields are required.

    Top White Papers and Webcasts

    • The operational costs of managing an x86 base are taxing IT budgets, making it difficult to fund and staff new initiatives. Today's IT organization must seek efficiencies in its operations and shift to a more agile infrastructure that's flexible enough to adapt to future changes in the business. Read this Q & A session with Jed Scaramella, research manager for IDC's Enterprise Platforms and Data Center Trends, to learn how the integrated nature of the blade platform delivers critically needed efficiencies …

    • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

    Most Popular Programming Stories

    More for Developers

    Latest Developer Headlines

    RSS Feeds