Thanks for your treeview starter code. it's awsome.
I have modified the program you posted in 2007 to show the files when
clicking the expanded directories. With some gleaning from tonny bjorn, i was
able to get the files from the directories that were not expandable which
i wasnt getting to begin with. The only trouble i have is when you expand/contract a folder more than once, it doubles or triples the subfolder
names. Any way to correct this ? Also, how to get the path for the selected file.
Here is the modified code - It's pretty much as posted except for an additional textbox and button.
I changed the textbox multiline to a listbox which is easier to get the file name.
I have modified the program you posted in 2007 to show the files when
clicking the expanded directories. With some gleaning from tonny bjorn, i was
able to get the files from the directories that were not expandable which
i wasnt getting to begin with. The only trouble i have is when you expand/contract a folder more than once, it doubles or triples the subfolder
names. Any way to correct this ? Also, how to get the path for the selected file.
Here is the modified code - It's pretty much as posted except for an additional textbox and button.
I changed the textbox multiline to a listbox which is easier to get the file name.
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 GLOBAL UserSelected$ 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 LOCAL dummy$() DIM dummy$(0) DIALOG NEW PIXELS, 0, "my TreeView", , , 500, 400,%WS_SYSMENU OR %WS_MINIMIZEBOX TO hMain 'add treeview common control CONTROL ADD "SysTreeView32", hMain, %ID_TREE, "", 0, 0, 300, 300, _ %WS_CHILD OR %WS_VISIBLE OR %TVS_HASBUTTONS OR %TVS_HASLINES OR _ %TVS_LINESATROOT OR %TVS_SHOWSELALWAYS, %WS_EX_CLIENTEDGE CONTROL ADD BUTTON, hMain,201,"&Close",100,320,80,30 CONTROL ADD BUTTON, hMain,202,"&OK",100,360,80,30 CONTROL ADD LISTBOX, hMain,301,dummy$(),310,0,170,300,%WS_VSCROLL 'OR %ES_MULTILINE CONTROL ADD TEXTBOX, hMain,302,"",310,320,120,22',%ES_MULTILINE OR %WS_VSCROLL DIALOG SHOW MODAL hMain CALL TreeViewProc MSGBOX "File is "+userSelected$ END FUNCTION CALLBACK FUNCTION TreeViewProc() 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 LOCAL txt$,lResult$ LOCAL dirtosearch$ LOCAL dummy$() LOCAL path$ DIM dummy$(0) 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 CASE 201 'close button UserSelected$="" DIALOG END CBHNDL,0 CASE 202 'ok DIALOG END CBHNDL,1 CASE 301 'select a file from textbox LISTBOX GET TEXT CBHNDL,301 TO UserSelected$ CONTROL SET TEXT CBHNDL,302,UserSelected$ CASE 302 'file name text box CONTROL GET TEXT CBHNDL,302 TO UserSelected$ 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 ' txt$="" LISTBOX RESET CBHNDL,301 dirtosearch$=item(n) lResult$=DIR$(dirtosearch$+"\*.*",0) WHILE lresult$<>"" txt$ =LResult$ 'txt$+lResult$+$CRLF LISTBOX ADD CBHNDL,301,txt$ lResult$=DIR$ WEND CASE %TVN_SELCHANGING 'LAST 'FIRST 'KEYDOWN lpTV = CBLPARAM hTreeItem = @lpTV.ItemNew.hItem m = numItems: n = getItemNo(hTreeItem) txt$="" LISTBOX RESET CBHNDL,301 dirtosearch$=item(n) lResult$=DIR$(dirtosearch$+"\*.*",0) WHILE lresult$<>"" txt$ =lrEsult$ 'txt$+lResult$+$CRLF LISTBOX ADD CBHNDL,301,txt$ 'count&=count&+1 lResult$=DIR$ WEND 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 '--------------------------------------------------------------------------------
Comment