Sign in to follow this  
Followers 0

Questions about creating a file tree structure with TreeView

8 posts in this topic

So I am trying to create a file tree structure Using _FileListToArrayRec with GuiCtrlCreateTreeView. But i have some problems with levels of directorys. In my mind there is nothing wrong with my logic, but obviously it is, since i dont get the output i want :P 


Here is a printscreen of the outcome, the array is sorted so it feels like it should be pretty easy, but its not :(


Here is the working code

#include <File.au3>
#include <Array.au3>
#include <GUITreeview.au3>
#include <WINapiSHELLEX.au3>

Local $hGI = GUICreate("test", 500,500)
Local $hTreeView = GUICtrlCreateTreeView(0,0,500,500)


Local $arr = _GuictrlTreeview__FileListToArrayRec($hTreeView,"C:\Autoit\REMOVE", "*.au3||BackUp;.git*;___TrashCan")


Func _GuictrlTreeview__FileListToArrayRec($hTreeView, $sPath, $sFilter)
    if StringRight($sPath,1) == "\" Then $sPath = StringLeft($sPath, StringLen($sPath) - 1)
    if not FileExists($sPath) Then Return SetError(1,0,0)
    Local $aFileList = _FileListToArrayRec($sPath, $sFilter, $FLTAR_FILESFOLDERS, $FLTAR_RECUR, $FLTAR_SORT, $FLTAR_FULLPATH)
    if @error Then Return SetError(1,0,0)

    Local $aParents[1] = [0]

    Local $sLastParentDirectory = False
    Local $hLastParentTreeItem = False
    Local $hLastParentChildItem = False

    ; Set default icons (late rreplaced with file associated icon
    $hImageList = _GUIImageList_Create(16, 16, 5, 1)
    _GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)

    ; Begin tree update

    For $i = 1 To $aFileList[0]
        Local $sCurFullFilePath = $aFileList[$i]
        Local $sCurFileName = _Misc_GetFileName($aFileList[$i], False)

        ;Get da icon
        Local $hIcon = _WinAPI_ShellExtractAssociatedIcon($sCurFullFilePath, 1)
        Local $hIcon_Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)

        ;If directory
        If FileGetAttrib($sCurFullFilePath) == "D" Then

            ; Check if sub has file to add
            If StringLeft($sCurFullFilePath, StringLen($sLastParentDirectory)) == $sLastParentDirectory Then

                $hLastParentChildItem = _GUICtrlTreeView_AddChild($hTreeView, $hLastParentTreeItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
                ;Loop will end here

            ;Create new parent folder & Update parents
            $sLastParentDirectory = $sCurFullFilePath
            $hLastParentTreeItem = _GUICtrlTreeView_Add($hTreeView, 0, StringFormat("%s", $sCurFileName), $hIcon_Index, $hIcon_Index)


            If Not $hLastParentChildItem Then
                ;ConsoleWrite($hLastParentTreeItem&" "&$sCurFileName&@CRLF)
                _GUICtrlTreeView_AddChild($hTreeView, $hLastParentTreeItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
                _GUICtrlTreeView_AddChild($hTreeView, $hLastParentChildItem, $sCurFileName, $hIcon_Index, $hIcon_Index)



    ; End update

    Return $aFileList


Func _Misc_GetFileName($sFilePath, $KeepExtension = True)
    ; Gets the filename
    Local $StringSPlit = StringSplit($sFilePath, "\")

    If Not $KeepExtension Then Return StringRegExpReplace($StringSPlit[$StringSPlit[0]], "\.(.*?)[a-zA-Z1234567890_-]{1,}+", "")
    Return $StringSPlit[$StringSPlit[0]]
EndFunc   ;==>_Misc_GetFileName


Any tips ?


Thanks in advance

Share this post

Link to post
Share on other sites

#6 ·  Posted (edited)

44 minutes ago, LarsJ said:

tarretarretarre, Here here here is all what you need need need. Post 3.

Damn near dumped my coffee on the kb when i read this...thanks for the laugh of the day LarsJ...


By the way, thanks for the example code.  I have a "Hatfield and McCoy's" kind of relationship with treeview controls...

Edited by kylomas

Forum Rules         Procedure for posting code

"I like pigs.  Dogs look up to us.  Cats look down on us.  Pigs treat us as equals."

- Sir Winston Churchill

Share this post

Link to post
Share on other sites

I solved it..... In the ghetto


I got what i was aiming for. I will share if anyone else wanna look@it.


Its really slow and uses 2 recurisve functions to: Sort files (windows style, folders first) 

#include <GuiTreeView.au3>
#include <WINapiSHELLEX.au3>
#include <array.au3>

$hGui = GUICreate("Demo1", 600, 400)
$hTreeView = _GUICtrlTreeView_Create($hGui, 10, 10, 580, 380)

Local $test = _GuictrlTreeview__FileListToArrayRec($hTreeView, @ScriptDir, ".au3", "BackUp;.git")


; Retrives a full array of directorys., here we use filters

Func _GuictrlTreeview__FileListToArrayRec($hTreeView, $sRoot, $sAcceptedFiles = ".", $sExcludedFolders = "")
    Local $aReturn[1];All files stored here in 1D array
    Local $AcceptedFiles = StringSplit($sAcceptedFiles, ";")
    Local $ExcludedFolders = StringSplit($sExcludedFolders, ";")
    $FileListToArray = _FileListToSortedArray($sRoot, $AcceptedFiles, $ExcludedFolders)

    ; Dummy icon control.
    Local $hImageList = _GUIImageList_Create(16, 16, 5, 1)
    _GUICtrlTreeView_SetNormalImageList($hTreeView, $hImageList)

    _SortedArrayToTreeView($aReturn, $FileListToArray, 0, $hImageList)
    Return $aReturn
EndFunc   ;==>_GuictrlTreeview__FileListToArrayRec

Until GUIGetMsg() = -3

Func _SortedArrayToTreeView(ByRef $aReturn, ByRef $sSourceFolder, $hItem, $hImageList)
    Local $sCurFileName = "unkown :P", $aFileList, $newItem, $hIcon, $aCurFileList, $hIcon_Index

    For $i = 2 To $sSourceFolder[0]; Last arg of array push lets us start from 2 instead so we can save 2 for stuff
        ; Current "file array"
        $aFileList = $sSourceFolder[$i]

        ; Get Type
        If IsArray($aFileList) Then
            $aCurFileList = $aFileList[1]
            _Array_Push($aReturn, $aCurFileList)
            $aCurFileList = $aFileList
            _Array_Push($aReturn, $aCurFileList)

        ; Get short name
        $sCurFileName = _________GetFileName($aCurFileList)

        ; Get icon of file
        $hIcon = _WinAPI_ShellExtractAssociatedIcon($aCurFileList, 1)
        $hIcon_Index = _GUIImageList_ReplaceIcon($hImageList, -1, $hIcon)

        ; Check if "Folder"
        If IsArray($aFileList) Then
            ;Ghetto get the folder name

            $newItem = _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sCurFileName, $hIcon_Index, $hIcon_Index)
            _SortedArrayToTreeView($aReturn, $aFileList, $newItem, $hImageList)

            If Not $sCurFileName Then

            Else; Regular file
                _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sCurFileName, $hIcon_Index, $hIcon_Index)


EndFunc   ;==>_SortedArrayToTreeView

;// Fuck yeah...
Func _FileListToSortedArray($sSourceFolder, $AcceptedFiles, $ExcludedFolders)
    Local $newTree[1]

    Local $sFile, $sCurFullFilePath, $DeniedFolder, $DeniedFile

    ; Force a trailing \
    If StringRight($sSourceFolder, 1) <> "\" Then $sSourceFolder &= "\"

    ; Add basedir to array
    _Array_Push($newTree, $sSourceFolder)

    ; Start the search
    Local $hSearch = FileFindFirstFile($sSourceFolder & "*.*")
    ; If no files found then return
    If $hSearch = -1 Then Return ; This is where we break the recursive loop <<<<<<<<<<<<<<<<<<<<<<<<<<

    ; Now run through the contents of the folder
    While 1
        ; reset
        $DeniedFolder = False
        $DeniedFile = False
        ; Get next match
        $sFile = FileFindNextFile($hSearch)
        $sCurFullFilePath = $sSourceFolder & $sFile

        If @error Then ExitLoop ; This is where we break the recursive loop <<<<<<<<<<<<<<<<<<<<<<<<<<

        ; Check if a folder
        If @extended Then
            ; If so then call the function recursively

            ;Check if exluced folder
            For $i = 1 To $ExcludedFolders[0]
                If StringInStr($sFile, $ExcludedFolders[$i]) Then $DeniedFolder = True

            If $DeniedFolder Then ContinueLoop

            Local $try = _FileListToSortedArray($sCurFullFilePath, $AcceptedFiles, $ExcludedFolders)
            If IsArray($try) Then
                _Array_Push($newTree, $try)

            ; If a file than write path and name
            For $i = 1 To $AcceptedFiles[0]
                If Not StringInStr($sFile, $AcceptedFiles[$i]) Then $DeniedFile = True
            If $DeniedFile Then ContinueLoop
            _Array_Push($newTree, $sCurFullFilePath)

    ;Sort this nigga
    _ArraySort($newTree, 0, 2)
    Return $newTree

EndFunc   ;==>_FileListToSortedArray

Func _Array_Push(ByRef $a, $v)
    If Not IsArray($a) Then
        ConsoleWrite("! _Array_Push used with non array" & @CRLF)
        Return False

    ReDim $a[$a[0] + 2]
    $a[$a[0] + 1] = $v
    $a[0] += 1
    Return $a[0]
EndFunc   ;==>_Array_Push

Func _________GetFileName($sFilePath)
    If Not StringInStr($sFilePath, "\") Then Return False; $sFilePath (THIS WILL IGNORE EMPTY DIRECTORYS) SEARCH FOR THIS
    Local $StringSplit = StringSplit($sFilePath, "\")
    If StringRegExp($StringSplit[$StringSplit[0]], "\.(.*?)[a-zA-Z1234567890_-]{1,}+") Then Return $StringSplit[$StringSplit[0]]
    Return $StringSplit[$StringSplit[0] - 1]
EndFunc   ;==>_Misc_GetFileName


Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • corgano
      By corgano
      I can't explain easily what i want to do, so i made a picture:

      What i want to do is to specify a treeview item, and then be able to move it right to be a child of the previous item, or left to do the opposite (make a child into a sibling). I also want to move and child items of the target with it, like in the bottom half of the above image depicts. However I didn't see any functions in the help file to move items around. All i want is a button that when pressed, makes the selected item and any of selected item's children move one layer to the right / left. Does anyone know how?

      Edit: something along the lines of _GUICtrlTreeView_Level but SET level
    • Tjalve
      By Tjalve
      Hi everyone. Im creating a GUI for an application. Im usinga  treeview item and i want to add some information to the side of the treeview based on what cilditem you are pressing. For the moment i have a "get info" button that works. But that means that you have to select your child in the treeview, and then press a button to gte the info. I want the info to be visable as soon as you select it.
      With uther controls you can just add it to the loop but it doesnt seem to work with tyhe UDF version of the treeview control. Is there anything I can do?
      #include <GUIConstantsEx.au3> #include <GuiTreeView.au3> #include <MsgBoxConstants.au3> #include <WindowsConstants.au3> ;~ Create GUI dim $guilabel[7] local $currentlevel = 1 Local $hGui = GUICreate( "Grejs", 1000, 500, 600, 300, BitOR( $GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX ) ) Local $iBorderWidth = 4, $aPos = WinGetClientSize( $hGui ) $idTV = _GUICtrlTreeView_Create($hGui, $iBorderWidth, $iBorderWidth, $aPos[0]-2*$iBorderWidth-400, $aPos[1]-2*$iBorderWidth-30 ) $root_level = _GUICtrlTreeView_Add($idTV,0,"Root") $item1 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child1") $item2 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child2") $item3 = _GUICtrlTreeView_AddChild($idTV, $root_level, "child3") ;~ Start Gui GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idTV MsgBox(0,"","") EndSwitch WEnd GUIDelete($hGui) Exit In this example, i want the msgbox to appear whenevr i select something in the treeview. It ios not my full code, but its an example of the problam i have. Help is much appritiated
    • Trolleule
      By Trolleule
      i'm building a "Jump To" registry key function and trying to get access to the regedit treeview control like this:
      #include <GUIConstants.au3> #include <GuiTreeView.au3> #include <TreeViewConstants.au3> #include <SendMessage.au3> #include <WinAPI.au3> Global $h_item ShellExecute("regedit.exe") ;~ Local $pid = ProcessExists("regedit.exe") ;~ If $pid Then ;~ $h_tree = WinHandFromPID($pid, "[CLASS:RegEdit_RegEdit]") ;~ WinActivate("[CLASS:RegEdit_RegEdit]", "") ;~ EndIf WinWaitActive("[CLASS:RegEdit_RegEdit]", "") ;~ WinActivate("[CLASS:RegEdit_RegEdit]", "") ;~ WinSetState("[CLASS:RegEdit_RegEdit]", "", @SW_SHOW) ; activate ;~ WinSetState("[CLASS:RegEdit_RegEdit]", "", @SW_RESTORE) ; activate ;~ WinSetState("[CLASS:RegEdit_RegEdit]", "", @SW_RESTORE) ; activate $h_tree = WinGetHandle("[CLASS:RegEdit_RegEdit]", "") ;~ $ret = _WinAPI_ShowWindow($h_tree, @SW_RESTORE) $ctrl = ControlGetHandle($h_tree, "", "[CLASS:SysTreeView32]") ConsoleWrite("$h_tree: " & $h_tree & @CRLF) ConsoleWrite("$ctrl: " & $ctrl & @CRLF) $show = GUICtrlCreateButton("Show", 70, 180, 70, 20) Show() ;~ While 1 ;~ Sleep(200) ;~ WEnd Func Show() $result = "" _SendMessage($ctrl, $WM_SETFOCUS, 0, 0) If @error Then ConsoleWrite("error" & @CRLF) $h_item = _SendMessage($ctrl, $TVM_GETNEXTITEM, $TVGN_ROOT, 0) $split = StringSplit("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", "\") For $i=1 To $split[0] ConsoleWrite("item bevor findkey: " & $h_item & @CRLF) $h_item = FindKey($h_item, $split[$i]) If $h_item = 0 Then Return _SendMessage($ctrl, $TVM_SELECTITEM, 0x0009, $h_item) ; expand tree _GUICtrlTreeView_Expand($ctrl, $h_item) Next MsgBox(0, "dsfsdf", "sdfsf") Exit EndFunc Func FindKey($hItemParent, $sKey) $h_item = _SendMessage($ctrl, $TVM_GETNEXTITEM, $TVGN_CHILD, $hItemParent) ConsoleWrite("child : " & $h_item & " key: " & $sKey & " parent: " & $hItemParent & " parent text: " & _GUICtrlTreeView_GetText($ctrl, $hItemParent) & @CRLF) While $h_item <> 0 Local $sItemText = _GUICtrlTreeView_GetText($ctrl, $h_item) ConsoleWrite("text : " & $sItemText & @CRLF) If $sItemText = $sKey Then Return $h_item $h_item = _SendMessage($ctrl, $TVM_GETNEXTITEM, $TVGN_NEXT, $h_item) ConsoleWrite("next : " & $h_item & @CRLF) WEnd ConsoleWrite("not found" & @CRLF) Return 0 EndFunc it's working, when i start regedit.exe within my app. But can't get it work when regedit.exe already open. Some ideas?
    • Kanashius
      By Kanashius
      This UDF can be used to make a Treeview and/or Listview able to browse Files.
      If you like it, please leave me a comment, also if you have any suggestions to make it better or if you found bugs.
    • Wingens
      By Wingens
      i am trying to create a FileManager, now i know there are better programs out there to do it, but i think its fun to try and learn nu things.
      Now i am getting stuck in my code i created a button to select a driver/folder after that i put's in the driver/folder contant in the TreeView, but when i select something and click on my button copy.
      It returns a 0 instead of something else, when i add a value to the TreeView with: GuiCtrlCreateTreeViewItem and i select that one, then my copy button works.
      Hope you guys can help me find out/point in the right direction where i am going wrong with this. Any pointers to a nicer GUI or a cleaner script  would be appreciated
      Below find my code:
      #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <GuiStatusBar.au3> #include <ProgressConstants.au3> #include <TreeViewConstants.au3> #include <WindowsConstants.au3> #include <GuiTreeView.au3> ;------------------------------------------------------------------------------------------------------------------------------------------- #NoTrayIcon ;------------------------------------------------------------------------------------------------------------------------------------------- If @OSVersion = "WIN_XP" Then $OS = "Windows XP" EndIf If @OSVersion = "WIN_VISTA" Then $OS = "Windows Vista" EndIf If @OSVersion = "WIN_7" Then $OS = "Windows 7" EndIf If @OSVersion = "WIN_8" Then $OS = "Windows 8" EndIf If @OSVersion = "WIN_81" Then $OS = "Windows 8.1" EndIf ;------------------------------------------------------------------------------------------------------------------------------------------- $Form1 = GUICreate("", 615, 470, -1, -1, $WS_POPUPWINDOW) $TITLE = GUICtrlCreateLabel("FileManager", 256, 8, 103, 24) GUICtrlSetFont(-1, 12, 800, 0, "MS Sans Serif") GUICtrlSetState($TITLE, $GUI_DISABLE) $INFO = GUICtrlCreateLabel("Hostname:" & @TAB & @ComputerName & @CRLF & "OS:" & @TAB & @TAB & $OS, 16, 437, 200, 60) GUICtrlSetState($INFO, $GUI_DISABLE) GUICtrlCreateLabel("Source", 16, 16) $SOURCEPROGRESS = GUICtrlCreateProgress(16, 72, 289, 17, $PBS_SMOOTH) $SOURCETREE = GUICtrlCreateTreeView(16, 104, 289, 305, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) GUICtrlCreateTreeViewItem("Test1", $SOURCETREE) $SOURCEINPUT = GUICtrlCreateInput("", 16, 40, 121, 21) GUICtrlSetState($SOURCEINPUT, $GUI_DISABLE) $SELECTSOURCE = GUICtrlCreateButton("...", 144, 42, 43, 17) GUICtrlCreateLabel("Target", 568, 16) $TARGETPROGRESS = GUICtrlCreateProgress(312, 72, 289, 17, $PBS_SMOOTH) $TARGETTREE = GUICtrlCreateTreeView(312, 104, 289, 305, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE) $TARGETINPUT = GUICtrlCreateInput("", 480, 40, 121, 21) GUICtrlSetState($TARGETINPUT, $GUI_DISABLE) $SELECTTARGET = GUICtrlCreateButton("...", 432, 42, 43, 17) $COPY = GUICtrlCreateButton("Copy", 182, 440, 75, 25) $MOVE = GUICtrlCreateButton("Move", 270, 440, 75, 25) $DELETE = GUICtrlCreateButton("Delete", 358, 440, 75, 25) $RENAME = GUICtrlCreateButton("Rename", 446, 440, 75, 25) $CLOSE = GUICtrlCreateButton("Exit", 534, 440, 75 , 25) GUISetState(@SW_SHOW) ;------------------------------------------------------------------------------------------------------------------------------------------- While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $CLOSE Exit Case $SELECTSOURCE SELECTSOURCE() Case $SELECTTARGET SELECTTARGET() Case $COPY COPY() EndSwitch WEnd ;------------------------------------------------------------------------------------------------------------------------------------------- Func SELECTSOURCE() $VAR = FileSelectFolder("Select Source drive/folder", "") GUICtrlSetData($SOURCEINPUT, $VAR) Local $iWait = 10 Local $iSavPos = 0 Do For $i = $iSavPos To 100 GUICtrlSetData($SOURCEPROGRESS, $i) Sleep($iWait) $iSavPos = $i Next Until $iSavPos = 100 _GUICtrlTreeView_BeginUpdate($SOURCETREE) ListFiles_FolderSOURCE($VAR & "\", 0) _GUICtrlTreeView_EndUpdate($SOURCETREE) EndFunc ;------------------------------------------------------------------------------------------------------------------------------------------- Func SELECTTARGET() $VAR = FileSelectFolder("Select Source drive/folder", "") GUICtrlSetData($TARGETINPUT, $VAR) Local $iWait = 10 Local $iSavPos = 0 Do For $i = $iSavPos To 100 GUICtrlSetData($TARGETPROGRESS, $i) Sleep($iWait) $iSavPos = $i Next Until $iSavPos = 100 _GUICtrlTreeView_BeginUpdate($TARGETTREE) ListFiles_FolderTARGET($VAR & "\", 0) _GUICtrlTreeView_EndUpdate($TARGETTREE) EndFunc ;------------------------------------------------------------------------------------------------------------------------------------------- Func ListFiles_FolderSOURCE($SourceFolder, $Item) Local $File If StringRight($SourceFolder, 1) <> "" Then $SourceFolder &= "" Local $Search = FileFindFirstFile($SourceFolder & "*.*") If $Search = -1 Then Return While 1 $File = FileFindNextFile($Search) If @error Then ExitLoop If @extended Then ListFiles_FolderSOURCE($SourceFolder & $File, _GUICtrlTreeView_AddChild($SOURCETREE, $Item, $File)) Else _GUICtrlTreeView_AddChild($SOURCETREE, $Item, $File) EndIf WEnd FileClose($Search) EndFunc ;------------------------------------------------------------------------------------------------------------------------------------------- Func ListFiles_FolderTARGET($TargetFolder, $Item) Local $File If StringRight($TargetFolder, 1) <> "" Then $TargetFolder &= "" Local $Search = FileFindFirstFile($TargetFolder & "*.*") If $Search = -1 Then Return While 1 $File = FileFindNextFile($Search) If @error Then ExitLoop If @extended Then ListFiles_FolderTARGET($TargetFolder & $File, _GUICtrlTreeView_AddChild($TARGETTREE, $Item, $File)) Else _GUICtrlTreeView_AddChild($TARGETTREE, $Item, $File) EndIf WEnd FileClose($Search) EndFunc ;------------------------------------------------------------------------------------------------------------------------------------------- Func COPY() $VAR = GUICtrlRead($SOURCETREE) If $VAR = 0 Then MsgBox($MB_SYSTEMMODAL, "Warning!", "No item currently selected") Else $sText = GUICtrlRead($VAR, 1) ; Get the text of the treeview item If $sText == "" Then MsgBox($MB_SYSTEMMODAL, "Warning!", "Error while retrieving info about selected item") Else MsgBox($MB_SYSTEMMODAL, "FileManager", "Current item selected is: " & $sText) EndIf EndIf EndFunc ;------------------------------------------------------------------------------------------------------------------------------------------- ;-------------------------------------------------------------------------------------------------------------------------------------------