CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14

Hybrid View

  1. #1
    Join Date
    Sep 1999
    Location
    Salisburyl UK
    Posts
    324

    CTreeCtrl SOOO SLOW !

    Hi All..
    I have an application which has a CTreeCtrl on a dialog. I need to add a large number of Items to it. It is possible that upwards of 18000 items may be added at one time. I have tested this, and even in release, this opperation can take 50 minuits or so !!!!
    This is a bit of a show stopper for me.

    My question is, why does it take so long and what can I do to speed such an opperation up (A LOT!).

    I suspect that something is searching in the TreeCtrl (for the parent Item perhaps), as the time taken to a add an Item gets progressivly slower as Items are added.

    Id realy appriciate the help of any Gurus out there who may have any idea how I can proceed!

    Many thanks
    Phill

  2. #2
    Join Date
    Jul 2005
    Posts
    767

    Re: CTreeCtrl SOOO SLOW !

    Actaully the regedit or Explorer that we use day in and out may be holding several thousands elements. So As I think one good approach would be not to dump all the 18000 or so elements at once but add/delete them on need basis, you could use the notifications TVN_ITEMEXPANDED, TVN_ITEMEXPANDING, TVN_SETDISPINFO and/or TVN_GETDISPINFO for your purpose.

    Also have a look at this.
    Last edited by MrBeans; June 12th, 2006 at 11:10 AM.

  3. #3
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: CTreeCtrl SOOO SLOW !

    You need to use a Virtual Tree Control and handle the TVN_GETDISPINFO message. Check out the LVSelState example in the post which contains an example for a virtual list control. This example is a dialog app which displays 10,000 -> 1 million virtual list entries. The code for a tree view is very similar.

    Code that fills the virtual listview control in LVSelState example:
    Code:
    // Method: Populate
    // Purpose: Called within the Retrieve button to add items to
    // the list control.
    HRESULT Populate( CListCtrl& ctlList )
    {
    HRESULT hr = S_OK;
     
    // Add a wait cursor
    CWaitCursor wait;
     
    long lIndex = 0;
    LVITEM lvitem = { 0 };
    lvitem.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
    int iItem = 0, iActualItem = 0;
     
    // Lock the List Control window so it doesn't look
    // like crap while filling
    ctlList.LockWindowUpdate();
     
    // Lock the list
    CAutoLockT< CLVItemDataList > lock( &m_LVItemDataList );
     
    // Cycle through the list and add each item into the list control
    for(CLVItemDataList::iterator it = m_LVItemDataList.begin();
    	it < m_LVItemDataList.end();
    	it++)
    {
    	CLVItemData* pLVItemData = (*it);
    	lvitem.iItem = iItem;
    	lvitem.iSubItem = 0;
    	lvitem.lParam = reinterpret_cast<LPARAM>(pLVItemData);
     
    	// Tell the list control to become 'Virtual' and request display
    	// data from the lvitem.lParam.
    	// See CLVSelStateDlg::OnLvnGetdispinfoList for where this happens
    lvitem.iImage = I_IMAGECALLBACK;
    	lvitem.pszText = LPSTR_TEXTCALLBACK;
    	lvitem.cchTextMax = MAX_LVITEMLEN;
     
    	// Insert the item
    ctlList.InsertItem(&lvitem);
     
    	// Set the text for each column (all virtual callbacks)
    ctlList.SetItemText(iItem, 0, LPSTR_TEXTCALLBACK);
    	ctlList.SetItemText(iItem, 1, LPSTR_TEXTCALLBACK);
    	ctlList.SetItemText(iItem, 2, LPSTR_TEXTCALLBACK);
    	iItem++;
     
    	// Check if user cancelled operation 
    if( WAIT_OBJECT_0 
    	 == WaitForSingleObject( GetShutdownEvent(), 0 ) )
    	{
    	 return hr;
    	}
     
    	// Pump messages to allow cancel button click
    	// during control filling. Populating the control
    	// with thousands of records takes time, so we need
    	// to process messages to handle the cancel button
    	// and close messages
     
    if(!ProcessMessages( ))
    	{
    	 return hr;
    	}
     
    	// Restore the wait cursor
    	// (if you don't do this, the wait cursor may go
    	// away after pumping messages)
    wait.Restore();
    }
     
    // Unlock the List control window
    ctlList.UnlockWindowUpdate();
     
    return hr;
    }
    
    Of course, for best performance when dealing with tens of thousands or more items is to combine the virtual tree control with the on demand loading that Mr Bean mentioned.
    Last edited by Arjay; June 12th, 2006 at 11:18 AM.

  4. #4
    Join Date
    Jul 2005
    Posts
    767

    Re: CTreeCtrl SOOO SLOW !

    Arjay: I think you have mixed up Virtual List control with Virtual Tree Control . It would be nice if you can provide an Virtual Tree Control example.
    Last edited by MrBeans; June 12th, 2006 at 11:23 AM.

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: CTreeCtrl SOOO SLOW !

    Quote Originally Posted by MrBeans
    Arjay: I think you have mixed up Virtual List control with Virtual Tree Control . It would be nice if you can provide an Virtual Tree Control example.
    My response includes code for the virtual list control, but mentions it's similar to the virtual tree control. Essentially, you can use the LVSelState example and replace the list view notification states and messages from LV to TV (e.g. NMLVDISPINFO becomes NMTVDISPINFO; LVITEM becomes TVITEM and so on).

    Here's the OnXXXGetDispInfo message handler, which I probably needed to include earlier. This is where all the virtual business happens:

    Code:
    // Method: OnLvnGetdispinfoList
    // Purpose: Handle the List Control Virtual callback. This handler gets
    // called everytime the list control needs to update its [visible] display
    // data.
    void CLVSelStateDlg::OnLvnGetdispinfoList(NMHDR *pNMHDR, LRESULT *pResult)
    {
      NMLVDISPINFO *pDispInfo
    	= reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
     
      // Get the list control item
    LVITEM* pItem = &(pDispInfo)->item;
     
      // Retrieve the CLVItemData object associated with this item
    CLVItemData* pLVItemData 
    	= reinterpret_cast<CLVItemData*>(pItem->lParam);
     
      if( NULL != pLVItemData )
      {
     
    	// Let the item method fill out the display data 
    pLVItemData->GetListViewItemInfo( pItem );
      }
     
      *pResult = 0;
    }


    Although this example is for a list view control, the virtual tree view control code is very similar. This example shows other useful concepts:
    • Locking the control while filling so the control doesn't look strange during the filling operation.
    • The virtual list control stores its data in an stl container (std::vector).
    • The std::vector is shared between two threads, so access to the vector is protected by a critical section.
    • While the control is filling, a wait cursor is displayed
    • During the filling of the control (and the filling of the vector in the secondary thread), the user can hit Cancel at any time and either filling operation will be gracefully halted.
    I didn't have a virtual tree view control example handy, so since the two virtual controls are similar, I thought this example appropro.

  6. #6
    Join Date
    Jul 2001
    Location
    Netherlands
    Posts
    751

    Re: CTreeCtrl SOOO SLOW !

    The reason it is so slow is that you go too DEEP.
    In a tree control you only want to go 2 levels deep( so you know whether a node is expandable or not).
    So after two levels you stop adding more items.
    And then you capture the TVN_SELCHANGED event to fill up the subtree at the selected item.

  7. #7
    Join Date
    Sep 1999
    Location
    Salisburyl UK
    Posts
    324

    Re: CTreeCtrl SOOO SLOW !

    Guys..
    Thanks for your responses.
    I have concidered using the "on demand" approach suggested by MrBeans, but unfortunatly the data I am presented with is "of the moment" so as to speak, and will be lost of it is not recorded. However I have not come accross this idea of a Virtual Tree Control suggested by Arjay, so I will look further into it.
    Arjay, thanks for the code example, if you have any more examples, Id be greatful !
    You would not belief the amount of time I have already wasted trying to get this method of presenting my data working !!!!! (but then maybe you would !)
    Thanks
    Philip....

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured