Tree View Dialog
A Win32 dialog example that builds a TreeView with an image list, adds nested nodes, and sub-classes the control to add its own behavior.
A complete tour of the classic TreeView control. In WM_INITDIALOG it attaches an image list (each node gets an icon index), then builds a three-level hierarchy - a server node with three database children, each holding Tables/Users/Views/Defaults leaves - using the TVAddItem helper (a thin wrapper over TreeView_InsertItem). It also demonstrates sub-classing: SetWindowLong(GWL_WNDPROC) swaps in a custom window procedure (TreeViewProc) so the tree can react to messages like right-clicks without touching the shell's code, saving the original proc for chaining. The Ok menu command shows adding a new child under the current selection at runtime.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CALLBACK MainDialog(HWND xHandle, UINT xMessage, WPARAM wParam, LPARAM lParam)
{
if(xMessage == WM_INITDIALOG) // Received A Initilize Dialog Message
{
MainDialog_hWnd = xHandle;
SendMessage(MainDialog_hWnd, (UINT)WM_SETTEXT, (WPARAM)0, (LPARAM)TitleCaption);
SendMessage(MainDialog_hWnd, WM_SETICON, TRUE, (LPARAM)LoadIcon(MainInstance, MAKEINTRESOURCE(100)) );
hmenu = LoadMenu(MainInstance, MAKEINTRESOURCE(500) );
hmenu = GetSubMenu(hmenu, 0);
TreeView = GetDlgItem(MainDialog_hWnd, 1000);
MakeTheImageList();
HTREEITEM Server, Database, MiscLeaf;
Server = TVAddItem(TreeView, TVI_ROOT, "DBServer", 0);
Database = TVAddItem(TreeView, Server, "DB_One", 2);
MiscLeaf = TVAddItem(TreeView, Database, "Tables", 3);
MiscLeaf = TVAddItem(TreeView, Database, "Users", 6);
MiscLeaf = TVAddItem(TreeView, Database, "Views", 4);
MiscLeaf = TVAddItem(TreeView, Database, "Defaults",9);
Database = TVAddItem(TreeView, Server, "DB_Two", 2);
MiscLeaf = TVAddItem(TreeView, Database, "Tables", 3);
MiscLeaf = TVAddItem(TreeView, Database, "Users", 6);
MiscLeaf = TVAddItem(TreeView, Database, "Views", 4);
MiscLeaf = TVAddItem(TreeView, Database, "Defaults", 9);
Database = TVAddItem(TreeView, Server, "DB_Three", 2);
MiscLeaf = TVAddItem(TreeView, Database, "Tables", 3);
MiscLeaf = TVAddItem(TreeView, Database, "Users", 6);
MiscLeaf = TVAddItem(TreeView, Database, "Views", 4);
MiscLeaf = TVAddItem(TreeView, Database, "Defaults", 9);
oldproc = (WNDPROC) SetWindowLong(TreeView, GWL_WNDPROC, (long) &TreeViewProc);
InvalidateRect(TreeView, NULL, 0);
CenterWindow(MainDialog_hWnd);
return 0;
}
//--------------------------------------------------------------------------
if(xMessage == WM_SIZE ) // Received A Message
{
int nWidth = LOWORD(lParam);
int nHeight = HIWORD(lParam);
MoveWindow(TreeView, 0, 0, nWidth, nHeight, TRUE);
return 0;
}
//--------------------------------------------------------------------------
if(xMessage == WM_COMMAND) // Received A Message
{
if(wParam==901) //- Ok (Dialog Menu Command)
{
// TreeView_DeleteItem(TreeView,seltree);
// TreeView_GetSelection(TreeView);
// TreeView_GetParent(TreeView, htree)
// TVAddItem(TreeView, htree, "Text");
HTREEITEM ThisTree = TreeView_GetSelection(TreeView);
TVAddItem(TreeView, ThisTree, "New Leaf", 5);
InvalidateRect(TreeView, NULL, 0);
return 0;
}
return 0;
}
//--------------------------------------------------------------------------
if(xMessage == WM_CLOSE) // Received Close Message
{
EndDialog(MainDialog_hWnd,0);
DestroyWindow(MainDialog_hWnd);
return 0;
}
//--------------------------------------------------------------------------
return 0;
}
The commented lines inside the command handler are a handy cheat-sheet of the other TreeView calls you will reach for: TreeView_DeleteItem, TreeView_GetSelection, and TreeView_GetParent. The WM_SIZE handler is what keeps the tree filling the dialog as it is resized, and on 64-bit builds remember to use SetWindowLongPtr instead of SetWindowLong for the sub-class swap.