Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

TreeView control starter code

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • TreeView control starter code

    I thought that this code might be useful as starter code to anyone new to the Treeview control. I know in my case, I like to see very simple code to begin with when dealing with an unfamiliar common control.

    I hope this code displays ok on this new forum.

    Code:
    #COMPILE EXE
    #DIM ALL
    #INCLUDE "win32api.inc"
    #INCLUDE "Commctrl.inc"
    
    'Include file statements 
    '========================================================================
    %ID_TREE = 100
    
    TYPE itemRef_UDT 
       hItem   AS LONG
       parent  AS LONG
       subDirs AS BYTE
       done    AS BYTE
    END TYPE
    
    GLOBAL hTree AS LONG
    GLOBAL numItems AS LONG
    GLOBAL maxDim AS LONG
    GLOBAL item() AS STRING
    GLOBAL itemRef() AS itemRef_UDT
    
    DECLARE FUNCTION TVInsertItem(LONG, LONG, STRING, BYTE) AS LONG
    DECLARE FUNCTION getItemNo(LONG) AS LONG
    DECLARE FUNCTION subDirsExist(STRING) AS BYTE
    DECLARE SUB getNextDirs(LONG)
    '========================================================================
    
    FUNCTION PBMAIN()
       LOCAL hMain AS LONG
       DIALOG NEW PIXELS, 0, "my TreeView", , , 400, 300,%WS_SYSMENU OR %WS_MINIMIZEBOX TO hMain
        'add treeview common control
       CONTROL ADD "SysTreeView32", hMain, %ID_TREE, "", 0, 0, 400, 300, _
                  %WS_CHILD OR %WS_VISIBLE OR %TVS_HASBUTTONS OR %TVS_HASLINES OR _
                  %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, %WS_EX_CLIENTEDGE
       DIALOG SHOW MODAL hMain CALL mainProc
       END FUNCTION
    
    CALLBACK FUNCTION mainProc()
       LOCAL i, m, n, hTreeItem, hItem, hParent, hChild AS LONG
       LOCAL s AS STRING, szTxt AS ASCIIZ*64
       LOCAL lpNmh AS NMHDR PTR
       LOCAL lpTV AS NM_TREEVIEW PTR
       LOCAL treeItem AS TV_ITEM
       LOCAL TVdi AS TV_DISPINFO
       SELECT CASE CBMSG
          CASE %WM_INITDIALOG
             maxDim = 2000
             DIM item(maxDim)
             DIM itemRef(maxDim)
             
             'find the first level children of C:\ 
             item(0) = "C:": getNextDirs 0
             
             'display the folders and files 
             CONTROL HANDLE CBHNDL, %ID_TREE TO hTree
             itemRef(0).hItem = TVInsertItem(hTree, 0, "C:\", 1)
             FOR i = 1 TO numItems
                s = PARSE$(item(i), "\", -1)
                hParent = itemRef(itemRef(i).parent).hItem
                hChild = TVInsertItem(hTree, hParent, s, itemRef(i).subDirs)
                itemRef(i).hItem = hChild
             NEXT i
             
             'open with first level folders... the children of C:\
             SendMessage hTree, %TVM_EXPAND, %TVE_EXPAND, itemRef(0).hItem   
          CASE %WM_PAINT
          CASE %WM_COMMAND
             SELECT CASE CBCTL
             END SELECT
          CASE %WM_NOTIFY
             lpNmh = CBLPARAM
             SELECT CASE @lpNmh.Code
                CASE %TVN_ITEMEXPANDING
                   'expand or collapse the treeview node hTreeItem
                   lpTV = CBLPARAM
                   hTreeItem = @lpTV.ItemNew.hItem 
                   m = numItems: n = getItemNo(hTreeItem)
                   IF itemRef(n).done THEN EXIT FUNCTION
                   getNextDirs n
                   FOR i = m + 1 TO numItems
                      s = PARSE$(item(i), "\", -1)
                      hParent = itemRef(itemRef(i).parent).hItem
                      hChild = TVInsertItem(hTree, hParent, s, itemRef(i).subDirs)
                      itemRef(i).hItem = hChild
                   NEXT i
             END SELECT   
          CASE %WM_SYSCOMMAND
          CASE %WM_DESTROY
       END SELECT
    END FUNCTION
    
    FUNCTION getItemNo(hTreeItem AS LONG) AS LONG
       'get itemNo corresponding to item's handle
       'hTreeItem  = item handle
       'numItems   = number of items defined (nodes of treeview)
       '===================================================================
       LOCAL i, n AS LONG
       FOR i = 1 TO numItems
          IF itemRef(i).hItem = hTreeItem THEN n = i: EXIT FOR
       NEXT i
       FUNCTION = n
    END FUNCTION
    
    FUNCTION TVInsertItem(hTree AS LONG, hParent AS LONG, sTxt AS STRING, b AS BYTE) AS LONG
       'insert item into treeview control
       '--------------------------------------------------------------------------------
       'hTree   = handle of treeview control
       'hParent = handle of parent to item
       'sTxt    = string label identifying item
       'b       = set if children exist for this item
       '================================================================================
       LOCAL tv_insert AS TV_INSERTSTRUCT
       tv_insert.hParent              = hParent
       tv_insert.Item.Item.mask       = %TVIF_TEXT OR %TVIF_CHILDREN
       tv_insert.Item.Item.pszText    = STRPTR(sTxt)
       tv_insert.Item.Item.cchTextMax = LEN(sTxt)
       IF b THEN tv_insert.Item.Item.cChildren = 1
       FUNCTION = TreeView_InsertItem(hTree, tv_insert)
    END FUNCTION
    
    SUB getNextDirs(itemNo AS LONG)
       'find next first level children of itemNo
       'update global item(), itemRef(), and numItems
       '-------------------------------------------------------------------
       'item()    = array of folder names
       'itemRef() = array of folder info UDTs 
       'numItems  = number of nodes identified so far
       '===================================================================
       LOCAL s, sParent AS STRING
       LOCAL attr, i, k, n, nDim AS LONG
       DIM sTemp(maxDim) AS STRING
       sParent = RTRIM$(item(itemNo), "\") + "\"
       attr = %SUBDIR 'OR %READONLY OR %HIDDEN OR %SYSTEM 
       s = DIR$(sParent, attr)
       IF LEN(s) THEN 
          k = GETATTR(sParent + s) AND %SUBDIR
          IF k THEN INCR n: sTemp(n) = s
          DO 
             s = DIR$: k = 0: IF LEN(s) = 0 THEN EXIT DO
             k = GETATTR(sParent + s) AND %SUBDIR
             IF k THEN INCR n: sTemp(n) = s
          LOOP
       END IF
       itemRef(numItems).done = 1
       'found n subdirectories of itemNo
       '... now update numItems, item(), and itemRef() 
       IF n = 0 THEN EXIT SUB
       numItems = numItems + n
       nDim = UBOUND(item)
       IF nDim < numItems THEN 'redim arrays if necessary
          nDim = numItems + 1000
          REDIM PRESERVE item(nDim)
          REDIM PRESERVE itemRef(nDim)
       END IF 
       FOR i = 1 TO n
          s = sParent + sTemp(i)
          item(numItems - n + i) = s
          itemRef(numItems - n + i).parent = itemNo
          itemRef(numItems - n + i).subDirs = subDirsExist(s)
       NEXT i
    END SUB
    
    FUNCTION subDirsExist(sItem AS STRING) AS BYTE
       'return 1 if any children exist for this node
       'this function is needed to determine if node needs a [+] button
       '----------------------------------------------------------------
       'sItem  = name of node
       '================================================================
       LOCAL attr, k AS LONG
       LOCAL s, sParent AS STRING
       sParent = RTRIM$(sItem, "\") + "\"
       attr = %SUBDIR 'OR %READONLY OR %HIDDEN OR %SYSTEM 
       s = DIR$(sParent, attr)
       IF LEN(s) THEN 
          k = GETATTR(sParent + s) AND %SUBDIR
          DO WHILE LEN(s) AND k = 0
             s = DIR$: IF LEN(s) = 0 THEN EXIT DO
             k = GETATTR(sParent + s) AND %SUBDIR
          LOOP 
       END IF
       FUNCTION = SGN(k)
    END FUNCTION
    Last edited by Charles Dietz; 30 Aug 2007, 10:11 PM.
Working...
X