What's New
Q & A
Tip Jar
C# Helper...
Follow VBHelper on Twitter
MSDN Visual Basic Community
TitleAdd nodes to a TreeView control when the user expands a node
DescriptionThis example shows how to add nodes to a TreeView control when the user expands a node in Visual Basic 6. It subclasses and watches for the TVN_ITEMEXPANDING/TVE_EXPAND and TVN_ITEMEXPANDED/TVE_COLLAPSE notifications.
KeywordsTreeView, expanding, collapsing, node
When the program starts, it adds some root nodes to the TreeView. It does NOT add any children to those nodes. Instead it sends the TreeView the TVM_GETNEXTITEM message to get the handle for the newly created items. It then sends the TVM_SETITEM message to tell the TreeView that these nodes have 1 child.

This makes the TreeView display the + sign next to the nodes even though they don't really have children. It also makes the TreeView send messages to its container (the form) when a node is expanded or collapsed.

The program then calls subroutine SubclassMe to subclass its form so it can watch for these messages.

' Load the top-level folders.
Private Sub Form_Load()
Dim root_text() As String
Dim i As Integer
Dim h_root As Long
Dim tv_item As TVITEM
Dim root_node As Node

    ' Display root lines.
    trvFolders.LineStyle = tvwRootLines

    ' Initially there is no root.
    h_root = 0

    ' Add some entries.
    root_text = Split("Ash,Beech,Cherry,Date", ",")
    For i = LBound(root_text) To UBound(root_text)
        ' Make a node for the next entry.
        Set root_node = _

        ' Get the node's item handle.
        ' (It's the next item after the previous one.)
        ' For the first item, get the root.
        If h_root = 0 Then
            h_root = SendMessageL(trvFolders.hWnd, _
                TVM_GETNEXTITEM, TVGN_ROOT, ByVal 0&)
            h_root = SendMessageL(trvFolders.hWnd, _
                TVM_GETNEXTITEM, TVGN_NEXT, h_root)
        End If

        ' Save the item's handle.
        root_node.Tag = h_root

        ' Set the item's number of children to 1.
        tv_item.mask = TVIF_CHILDREN
        tv_item.hItem = h_root
        tv_item.cChildren = 1
        SendMessage trvFolders.hWnd, TVM_SETITEM, ByVal 0&, _
    Next i

    ' Subclass the form to watch for TreeView messages.
    SubclassMe Me, trvFolders
End Sub
Subroutine SubclassMe saves references to the program's form and its TreeView control. It then subclasses the form to watch for the form's notification messages.
' Subclass this object.
Public Sub SubclassMe(ByVal client_form As Form, ByVal trv _
    As TreeView)
    ' Save the form.
    Set m_ClientForm = client_form

    ' Save the TreeView's hWnd.
    Set m_TreeView = trv

    ' Subclass.
    m_OldWindowProc = SetWindowLong( _
        client_form.hWnd, GWL_WNDPROC, _
        AddressOf NewWindowProc)
End Sub
The new WindowProc is called when the form receives a Windows message. If the messages is WM_NCDESTROY, the routine uninstalls the WindowProc.

When the user expands one of the root nodes, the form receives a WM_NOTIFY message. It copies the data at address lParam into a notification header structure and examines its code field. If code is TVN_ITEMEXPANDING, it copies the data at address lParam into a TreeView notification structure and examines its action field. If action is TVE_EXPAND, then one of the nodes is about to expand. The routine calls the form's Expanding method, passing it the TreeView Node corresponding to the node's handle.

When the user collapses one of the root nodes, the routine does basically the same thing except it looks for the code TVN_ITEMEXPANDED and the action TVE_COLLAPSE. When it sees them, it calls the form's Collapsing to tell the form what's going on. It then sends the TreeView the message TVM_EXPAND with parameters TVE_COLLAPSE Or TVE_COLLAPSERESET. That makes the control collapse the node and remove the previously added children.

' Display message names.
Public Function NewWindowProc(ByVal hWnd As Long, ByVal msg _
    As Long, ByVal wParam As Long, ByVal lParam As Long) As _
Const WM_NOTIFY = &H4E

Dim notifiy_header As NMHDR
Dim notifiy_tv_text As NMTREEVIEW_textptr
Dim h_item As Long

    ' If we're being destroyed,
    ' restore the original WindowProc.
    If msg = WM_NCDESTROY Then
        SetWindowLong _
            hWnd, GWL_WNDPROC, _
    End If

    ' See if this we're expanding or collapsing.
    ' See if this is WM_NOTIFY.
    If msg = WM_NOTIFY Then
        ' Copy the WM_NOTIFY details into the
        ' notifiy_header structure.
        CopyMemory notifiy_header, ByVal lParam, _

        ' See if the message is coming
        ' from the target TreeView.
        If notifiy_header.hwndFrom = m_TreeView.hWnd Then
            ' This is the right TreeView.
            ' See what kind of notification this is.
            If notifiy_header.code = TVN_ITEMEXPANDING Then
                ' Examine the notify information.
                CopyMemory notifiy_tv_text, ByVal lParam, _

                ' See what operation this is.
                If notifiy_tv_text.action = TVE_EXPAND Then
                    ' We are expanding.
                    ' Call the form's AddItems method,
                    ' passing it the expanding node.
                    h_item = notifiy_tv_text.itemNew.hItem
                    m_ClientForm.Expanding _
                End If
            ElseIf notifiy_header.code = TVN_ITEMEXPANDED _
                ' Examine the notify information.
                CopyMemory notifiy_tv_text, ByVal lParam, _

                ' See what operation this is.
                If notifiy_tv_text.action = TVE_COLLAPSE _
                    ' We are collapsing.
                    ' Call the form's Collapsing method.
                    h_item = notifiy_tv_text.itemNew.hItem
                    m_ClientForm.Collapsing _

                    ' Collapse the item, removing its
                    ' children.
                    SendMessageL m_TreeView.hWnd, _
                        TVM_EXPAND, _
                        TVE_COLLAPSE Or TVE_COLLAPSERESET, _
                End If
            End If ' End If TVN_ITEMEXPANDING or
                ' TVN_ITEMEXPANDED.
        End If ' End If message is from the target TreeView.
    End If ' End If msg = WM_NOTIFY

    ' Process the message normally. Very important!
    NewWindowProc = CallWindowProc( _
        m_OldWindowProc, hWnd, msg, wParam, _
End Function
Function FindNodeByTag searches through the TreeView's nodes to find one with the given Tag value.
' Find the node with this Tag value.
Private Function FindNodeByTag(ByVal tag_value As Long) As _
Dim test_node As Node

    ' Examine each node.
    For Each test_node In m_TreeView.Nodes
        ' See if this is the node we want.
        If test_node.Tag = tag_value Then
            ' This is the node. Return it.
            Set FindNodeByTag = test_node
            Exit Function
        End If
    Next test_node

    ' We didn't find it.
    Set FindNodeByTag = Nothing
End Function
The main program's Expanding method adds two new children to the expanding node. The children give the current date and time. If you open and close the root node, you will see the time change.
' We are expanding this item. Add more items as appropriate.
Public Sub Expanding(ByVal expanding_node As Node)
    ' Debug.Print "Expanding " & expanding_node.Text

    ' Add some children to the node.
    trvFolders.Nodes.Add Relative:=expanding_node, _
        Relationship:=tvwChild, Text:=Date
    trvFolders.Nodes.Add Relative:=expanding_node, _
        Relationship:=tvwChild, Text:=Time
End Sub
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.