ID: Q131278
The information in this article applies to:
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.
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 kbTreeView kbGrpUser kbWinOS95 kbWinOS98
Issue type : kbhowto
Last Reviewed: January 2, 1999