Using cChildren Member of TV_ITEM to Add Speed & Use Less RAM

Last reviewed: September 29, 1995
Article ID: Q131278
The information in this article applies to:
  • Microsoft Win32 Application Programming Interface (API) included with:

        - Microsoft Windows NT version 3.51
        - Microsoft Windows 95 version 4.0
        - Microsoft Win32s version 1.3
    

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 reference words: 4.00 95 Common Control performance speed up
KBCategory: kbui kbcode
KBSubcategory: UsrCtl


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 29, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.