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);
}