Click here to Skip to main content
Licence 
First Posted 22 Aug 2000
Views 133,053
Bookmarked 23 times

Speeding up the tree control

By | 22 Aug 2000 | Article
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:

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

        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.

This 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 than this problem was in another system too. It helped to set the windows default language to that what uses all the problematic characters.

Back to the speed case.

I found there are actions what 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 was interesting was the case of deleting all items from the tree.

Possibly you will say: Stupid man, I will have not 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 automaticaly detroyed at its end, or
  • I will call DestoyWindow and than Create.

No one of this 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:

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 it's 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 cound 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

About the Author

Tibor Blazko

Software Developer (Senior)

Slovakia Slovakia

Member



Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralInitial painting problem in CTreeCtrl PinmemberAbhi Lahare21:14 8 May '06  
GeneralRe: Initial painting problem in CTreeCtrl PinmemberTibor Blazko21:44 8 May '06  
GeneralSolutions and strange behaviour PinmemberArccos3:09 6 Sep '05  
GeneralObvious but often forgot!! Pinmembereneam21:32 4 Feb '04  
GeneralIME Issue in CTreeCtrl Pinmemberboonshajayan22:33 25 Aug '03  
GeneralAnother optimization... well sort of... PinmemberTim Smith5:17 19 Jul '02  
GeneralProblem with Tree contol PinmemberMuddassir23:18 25 Apr '02  
Generala sample of a fast file system browsing CTreeCtrl PinmemberMarat Bedretdinov16:18 2 Jun '01  
GeneralThe final solution to the speed problem PinmemberMarcos Lima15:25 21 May '01  
GeneralRe: The final solution to the speed problem PinmemberAnonymous15:46 21 May '01  
GeneralRe: The final solution to the speed problem PinmemberRené Greiner21:04 5 Jul '01  
GeneralRe: The final solution to the speed problem PinmemberTibor Blazko21:07 5 Jul '01  
GeneralMy own tree control ( need help with UI ) PinsussRené Greiner21:48 30 Aug '00  
GeneralRe: My own tree control ( need help with UI ) PinsussPeter22:05 17 Sep '00  
GeneralOWN TREE CONTROL PinmemberTibor Blazko20:52 5 Jul '01  
GeneralRe: My own tree control ( need help with UI ) Pinmemberroger_long21:01 17 Dec '07  
GeneralInsert an item PinsussRené Greiner1:25 28 Aug '00  
GeneralSpeed up PinsussMartin Bohring8:48 25 Aug '00  
GeneralSpeed up PinsussMartin Bohring8:48 25 Aug '00  
GeneralVirtual ListCtrl is much much faster PinsussTim Finer20:01 24 Aug '00  
GeneralSpeed PinsussSimon Brown10:05 24 Aug '00  
GeneralAnother spped improvement PinsussSteve Driessens17:38 23 Aug '00  
GeneralRe: Another spped improvement Pinsusstibor blazko23:42 23 Aug '00  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    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 | Mobile
Web01 | 2.5.120517.1 | Last Updated 23 Aug 2000
Article Copyright 2000 by Tibor Blazko
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid