Skip to content

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.

Published Sep 4, 1999

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.

An unhandled error has occurred. Reload 🗙