HOWTO: Use cChildren of TV_ITEM to Add Speed & Use Less RAM

ID: Q131278


The information in this article applies to:
  • Microsoft Win32 Software Development Kit (SDK)
  • Microsoft Windows 2000


SUMMARY

The cChildren member of the TV_ITEM structure is used to denote the number of child items associated with a treeview item. When used correctly, the cChildren member helps an application go faster and use less memory.

Applications may specify I_CHILDRENCALLBACK for this member, instead of passing the actual number of child items. To retrieve the actual number of child items associated with a treeview item, I_CHILDRENCALLBACK causes the treeview to send a TVN_GETDISPINFO notification when the item needs to be redrawn.


MORE INFORMATION

In a treeview with the TVS_HASBUTTONS style, specify a nonzero value for the cChildren member to add the appropriate plus or minus (+/-) button (to denote expand or collapse) to the left of the treeview item, without having to insert each of the child items to the treeview. Specifying a zero value indicates that the particular item does not have any child items associated with it.

An application that does not use the cChildren member of the TV_ITEM structure when inserting items to the treeview has to insert each of the child items associated with that treeview item in order for the +/- button to show up.

Using the cChildren member, therefore, helps to speed up an application and reduce memory requirements by allowing the application to fill the tree on demand.

Applications such as the Explorer, WinHelp, and RegEdit, which display huge hierarchical structures, take advantage of this feature by initially inserting only the visible items of the tree. The child items associated with a particular item are not inserted until the user clicks the parent item to expand it. At that point, the treeview's parent window receives a TVN_ITEMEXPANDING notification message, and the application inserts the child items for that parent item:


   // WM_NOTIFY message handler
   LRESULT MsgNotifyTreeView(HWND hwnd,
                             UINT uMessage,
                             WPARAM wparam,
                             LPARAM lparam)
   {

       LPNMHDR  lpnmhdr = (LPNMHDR)lparam;

       // Just before the parent item gets EXPANDED,
       // add the children.

       if (lpnmhdr->code == TVN_ITEMEXPANDING)
       {
           LPNM_TREEVIEW lpNMTreeView;
           TV_ITEM   tvi;

           lpNMTreeView = (LPNM_TREEVIEW)lparam;
           tvi = lpNMTreeView->itemNew;

           if ((tvi.lParam == PARENT_NODE) &&
               (lpNMTreeView->action == TVE_EXPAND))
           {

               // Fill in the TV_ITEM struct
               // and call TreeView_InsertItem() for each child item.

           }
        }

        return DefWindowProc(hwnd, uMessage, wparam, lparam);
   } 
When the user clicks the same parent item to collapse it, the application removes all the child items from the tree by using TreeView_Expand (,,TVE_COLLAPSE | TVE_COLLAPSERESET). The TVN_ITEMEXPANDED notification message is a good place to do this:

   // WM_NOTIFY message handler
   LRESULT MsgNotifyTreeView(HWND hwnd,
                             UINT uMessage,
                             WPARAM wparam,
                             LPARAM lparam)
   {

       LPNMHDR  lpnmhdr = (LPNMHDR)lparam;

       // Just before the parent item is COLLAPSED,
       // remove the children.

       if (lpnmhdr->code == TVN_ITEMEXPANDED)
       {

           LPNM_TREEVIEW lpNMTreeView;
           TV_ITEM       tvi2;


           lpNMTreeView = (LPNM_TREEVIEW)lparam;
           tvi2 = lpNMTreeView->itemNew;


           // Do a TVE_COLLAPSERESET on the parent to minimize memory use.

           if ((lpNMTreeView->action == TVE_COLLAPSE) &&
               (tvi2.lParam == PARENT_NODE))
           {
                TreeView_Expand (ghWndTreeView,
                                 tvi2.hItem,
                                 TVE_COLLAPSE | TVE_COLLAPSERESET);
           }
      }
      return DefWindowProc(hwnd, uMessage, wparam, lparam);
   } 
Applications that dynamically change the number of child items associated with a particular treeview item may specify I_CHILDRENCALLBACK for the cChildren member of its TV_ITEM structure when it is inserted into the tree. Thereafter, when that treeview item needs to be redrawn, the treeview sends a TVN_GETDISPINFO to its parent window to retrieve the actual number of child items and display the +/- button to the left of the treeview item, as appropriate.

An application that uses I_CHILDRENCALLBACK may process the TVN_GETDISPINFO notification as follows:

   // WM_NOTIFY message handler
   LRESULT MsgNotifyTreeView(HWND hwnd,
                             UINT uMessage,
                             WPARAM wparam,
                             LPARAM lparam)
   {

       LPNMHDR  lpnmhdr = (LPNMHDR)lparam;

       if (lpnmhdr->code == TVN_GETDISPINFO)
       {
          TV_DISPINFO FAR *lptvdi;

          lptvdi = (TV_DISPINFO FAR *)lparam;

       if ((lptvdi->item.mask & TVIF_CHILDREN) &&
(lptvdi->item.lParam == PARENT_NODE))
          lptvdi->item.cChildren = 1;

       }

      return DefWindowProc(hwnd, uMessage, wparam, lparam);
   } 

Additional query words: Common Control performance speed up

Keywords : kbcode kbCtrl kbNTOS351 kbNTOS400 kbWinOS2000 kbSDKWin32 kbTreeView kbGrpUser kbWinOS95 kbWinOS98
Version : WINDOWS:
Platform : WINDOWS
Issue type : kbhowto


Last Reviewed: February 2, 2000
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.