Click here to Skip to main content
15,867,330 members
Articles / Desktop Programming / MFC

Speeding Up the Tree Control

Rate me:
Please Sign up or sign in to vote.
4.13/5 (5 votes)
22 Aug 2000 169.3K   28   24
Some notes on speed issues with the MS Tree control

Introduction

I was in a situation where my application became slower than I expected. The reason, I found, was the tree control's speed.

First problem was in drawing. I used my own OnPaint, and used a trick you can find in many examples:

C++
void CMyTreeCtrl::OnPaint()
{
    CPaintDC paintDc(this);

    CDC dc;
    dc.CreateCompatibleDC(&paintDc);

    CRect clientRect;
    GetClientRect(&clientRect);

    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&paintDc, clientRect.right, clientRect.bottom);

    CBitmap *pOldBitmap = dc.SelectObject(& bitmap);

    CWnd::DefWindowProc(WM_PAINT, (WPARAM)dc.m_hDC, 0);

    dc.SetBkMode(TRANSPARENT);

    HTREEITEM hItem = GetFirstVisibleItem();

    while(hItem != NULL)
    {
        //do here what you want

        hItem = GetNextVisibleItem(hItem);
    }

    paintDc.BitBlt(0, 0, clientRect.right, clientRect.bottom, 
                   &dc, 0, 0, SRCCOPY);

    dc.SelectObject(pOldBitmap);

    // Do not call CTreeCtrl::OnPaint() for painting messages
}

If you plan to use many items, then change the "//do here what you want" part to this:

C++
CRect rItemRect;
GetItemRect(hItem, &rItemRect, FALSE);
if(dc.RectVisible(rItemRect))
{
    //do here what you want
}
else
{
    break; //from while
}

This way, drawing speed improved.

Multiple Fonts

Maybe you will not believe it but there can be situations where the tree control can use two fonts. This happened (in non-Unicode case) when some items contained not-English characters.

These items were drawn with another font so my own drawing in client's rectangle was sometimes clipped. Both fonts sometimes displayed the problematic characters the same way, or sometimes the second font displayed them wrong way.

It only happened on some machines, and then this problem was in another system too. It helped to set the windows default language to that which uses all the problematic characters.

Back to the Speed Case

I found there are actions that are slow because of tree control's nature (or better their author's). All of the following speed problems will grow with item count, meaning a time dependency on item count is not linear but quadratic.

One of the slow operations was, as you can expect, InsertItem. To do something with this is difficult. When you have application where you will from time to time insert some items, then this will not be a problem.

What was worse, and for me surprising, was that a slower operation than InsertItem was DeleteItem. For me, what was interesting was the case of deleting all items from the tree.

Possibly you will say: Stupid man, I will not have this problem because:

  • I will use (optimized) DeleteAllItems, possibly with SetRedraw combination, or
  • I will never call any Delete because I have a tree in dialog so it will be automatically destroyed at its end, or
  • I will call DestoyWindow and than Create.

No one of these solutions will help you - they will all take similar time.

Hopefully, you will never have 65536 items in a MS tree control. Of course, this depends on machine speed but for full tree, it can take more than half hour to remove all items. If you think you will jump over it by using list-control solution (I know from message boards reading only), you will not win.

Trying to set the parent to NULL to eliminate possible DeleteItem notifications did not work either.

I started to experiment with own all items deleting. The funny thing is I never found a slower solution than DeleteAllItems. The best solution I found was this:

C++
SetRedraw(FALSE) 
//find last first-level item
HTREEITEM i1 = GetRootItem();
HTREEITEM i2 = i1;
while(i2 != NULL)
{
  i1 = i2;
  i2 = GetNextItem(i1, TVGN_NEXT);
}
//remove from end
while( i1 != NULL)
{
  i2 = GetNextItem(i1, TVGN_PREVIOUS);
  DeleteItem(i1);
  i1 = i2;
}
SetRedraw(TRUE) 

Note that calling SetRedraw(..) before and after the repeated operations stops the control from redrawing the control each time its contents are changed. This is a standard trick and works with most of the Windows common controls (thanks to Steve Driessens for this).

Overall, it was little bit quicker but similar to DeleteAllItems - minutes are still minutes. Plus, it is possible that at your machine, with your OS version, your commctrl.dll version will be slower (or faster) than this. In newer Windows versions (W2K experience), the situation is better. Adding SetRedraw()s and with Expand(hItem, TVE_COLLAPSE)s before your deletions, you can get a more usable state (you can do this in W9x/NT, but it won't result in any further speedup).

Maybe you will not agree with my methods, or have or know something better - please let know.

As an aside, try to using the spy tool on the workspace window in Developer Studio. From the class name, you will see that it does not use the system tree control.

There are some quicker non-MS tree controls but most are not free. Using them without source ownership could possibly bring problems with new OS versions.

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


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.

Comments and Discussions

 
QuestionFaster way to delete treeitems Pin
Sean_Huang1-Aug-19 1:44
Sean_Huang1-Aug-19 1:44 
GeneralInitial painting problem in CTreeCtrl Pin
Abhi Lahare8-May-06 21:14
Abhi Lahare8-May-06 21:14 
GeneralRe: Initial painting problem in CTreeCtrl Pin
Tibor Blazko8-May-06 21:44
Tibor Blazko8-May-06 21:44 
GeneralSolutions and strange behaviour Pin
Arccos6-Sep-05 3:09
Arccos6-Sep-05 3:09 
GeneralObvious but often forgot!! Pin
eneam4-Feb-04 21:32
eneam4-Feb-04 21:32 
GeneralIME Issue in CTreeCtrl Pin
boonshajayan25-Aug-03 22:33
boonshajayan25-Aug-03 22:33 
GeneralAnother optimization... well sort of... Pin
Tim Smith19-Jul-02 5:17
Tim Smith19-Jul-02 5:17 
GeneralProblem with Tree contol Pin
25-Apr-02 23:18
suss25-Apr-02 23:18 
Generala sample of a fast file system browsing CTreeCtrl Pin
Marat Bedretdinov2-Jun-01 16:18
Marat Bedretdinov2-Jun-01 16:18 
GeneralThe final solution to the speed problem Pin
21-May-01 15:25
suss21-May-01 15:25 
GeneralRe: The final solution to the speed problem Pin
21-May-01 15:46
suss21-May-01 15:46 
GeneralRe: The final solution to the speed problem Pin
René Greiner5-Jul-01 21:04
René Greiner5-Jul-01 21:04 
GeneralRe: The final solution to the speed problem Pin
Tibor Blazko5-Jul-01 21:07
Tibor Blazko5-Jul-01 21:07 
GeneralMy own tree control ( need help with UI ) Pin
René Greiner30-Aug-00 21:48
René Greiner30-Aug-00 21:48 
GeneralRe: My own tree control ( need help with UI ) Pin
Peter17-Sep-00 22:05
Peter17-Sep-00 22:05 
GeneralOWN TREE CONTROL Pin
Tibor Blazko5-Jul-01 20:52
Tibor Blazko5-Jul-01 20:52 
GeneralRe: My own tree control ( need help with UI ) Pin
roger_long17-Dec-07 21:01
roger_long17-Dec-07 21:01 
GeneralInsert an item Pin
René Greiner28-Aug-00 1:25
René Greiner28-Aug-00 1:25 
GeneralSpeed up Pin
Martin Bohring25-Aug-00 8:48
Martin Bohring25-Aug-00 8:48 
GeneralSpeed up Pin
Martin Bohring25-Aug-00 8:48
Martin Bohring25-Aug-00 8:48 
GeneralVirtual ListCtrl is much much faster Pin
Tim Finer24-Aug-00 20:01
Tim Finer24-Aug-00 20:01 
GeneralSpeed Pin
Simon Brown24-Aug-00 10:05
Simon Brown24-Aug-00 10:05 
GeneralAnother spped improvement Pin
Steve Driessens23-Aug-00 17:38
Steve Driessens23-Aug-00 17:38 
GeneralRe: Another spped improvement Pin
Tibor Blazko23-Aug-00 23:42
Tibor Blazko23-Aug-00 23:42 

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.