Jump to content

Path to TreeView


sulfurious
 Share

Recommended Posts

A function to fill a TreeView control with a path. Pass a variable containing the path, and the name of a TreeView control.

This one wrapped my brain around itself a few times before I figured it out. I am unsure if it handles system or hidden files. I built it to handle small directories, specifically the StartMenu directories. It seems to work on any directory, but it is slow on large ones.

Here it is, with a simple gui.

#include <GUIConstants.au3>
#include <file.au3>
#include <array.au3>
#include <GuiTreeView.au3>

Opt("GUIOnEventMode", 1)
$Form1 = GUICreate("A Tree View Form", 612, 426, 317, 121, -1, $WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "_EXIT")
GUICtrlCreateLabel("Some Label", 8, 8, 67, 17)
$inpROFdispname = GUICtrlCreateInput("Some Input Box", 8, 32, 200, 17, -1, $WS_EX_CLIENTEDGE)
GUICtrlSetState(-1,$GUI_DROPACCEPTED)
$cTV1 = GUICtrlCreateTreeView(224, 8, 377, 410,BitOr($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT _
, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
GUICtrlSetState(-1,$GUI_HIDE)
$Button1 = GUICtrlCreateButton("Button 1", 24, 368, 73, 33)
GUICtrlSetOnEvent(-1,"_go")
GUISetState(@SW_SHOW)
Sleep(2000)
While 1
    Sleep(1000)  ; Idle around
WEnd
GUIDelete()
Exit

Func _EXIT()
    Exit
EndFunc ;==>Generic exit function

Func _PathToTreeView($vPath,$cTree)
    ; DUMP DIRECTORIES AND SUBDIRECTORIES TO TEMP FILE
    RunWait(@Comspec & ' /c dir /b /s "' & $vPath & '" > "' & @TempDir & '\tmpOUTPUT.txt"', @WorkingDir, @SW_HIDE)
    If Not FileExists(@TempDir & '\tmpOUTPUT.txt') Then 
        SetError(1, 0, 0)
        Return
    EndIf
    Local $dfLIST = FileRead(@TempDir & '\tmpOUTPUT.txt')
    FileDelete(@TempDir & '\tmpOUTPUT.txt')

    ; MAKE ARRAYS AND SET VARIABLES
    $dfLIST = StringSplit(StringTrimRight($dfLIST, 1), @LF) ; list of dirs and files
    _ArraySort($dfLIST,0,1)
    $dLIST = _FileListToArray($vPath,"*",2) ; list of dirs
    _ArraySort($dLIST,0,1)
    $dSPLIT = StringSplit($vPath,"\") ; Parent Directories
    $dPOS = $dSPLIT[0] ; count to position of Working Directory
    $1POS = $dPOS + 1 ; position of first Sub Directory
    
    ; FIND MAX DIRECTORY DEPTH LEVEL (beyond target directory level)
    $mLEN = 0
    For $x = 1 To $dfLIST[0]
        If StringInStr(FileGetAttrib(StringStripCR($dfLIST[$x])),'d') = 0 Then ContinueLoop 
        $new = StringSplit(StringReplace($dfLIST[$x],$vPath & "\",""),"\")
        If $new[0] > $mLEN Then 
            $mLEN = $new[0]
        EndIf
    Next
    $mLEN-=1
    
    ; CREATE DIRECTORIES FIRST
    For $y = 1 To $dLIST[0]
        Assign(String($dLIST[$y]),GUICtrlCreateTreeViewItem($dLIST[$y],$cTree))
        _GUICtrlTreeViewSetState($cTree,-1,16)
        For $x = 1 To $dfLIST[0]
            $curDEPTH = $1POS + 1
            If StringInStr($dfLIST[$x],$vPath & "\" & $dLIST[$y]) = 0 Then ContinueLoop 
            If StringInStr(FileGetAttrib(StringStripCR($dfLIST[$x])),"d") Then
                $new = StringSplit($dfLIST[$x],"\")
                If $new[0] = $1POS + 1 Then ; this count = first sub dir layer
                    $new[$1POS+1] = StringStripCR($new[$1POS+1])
                    Assign(String($new[$1POS+1]),GUICtrlCreateTreeViewItem($new[$1POS+1],Eval($dLIST[$y])))
                    _GUICtrlTreeViewSetState($cTree,-1,16)
                    $dfLIST[$x] = ""
                ElseIf $new[0] > $1POS + 1 Then 
                    For $z = 1 to $mLEN ; check for which layer it belongs
                        If $new[0] = $curDEPTH + $z Then
                            $curDEPTH+=$z
                            $new[$curDEPTH] = StringStripCR($new[$curDEPTH])
                            Assign(String($new[$curDEPTH]),GUICtrlCreateTreeViewItem($new[$curDEPTH],Eval($new[$curDEPTH-1])))
                            _GUICtrlTreeViewSetState($cTree,-1,16)
                            $dfLIST[$x] = ""
                            ExitLoop
                        EndIf
                    Next
                EndIf
            EndIf   
        Next
    Next
    
    ; CREATE FILES SECOND
    For $x = 1 To $dfLIST[0]
        $curDEPTH = $1POS + 1
        If StringInStr(FileGetAttrib(StringStripCR($dfLIST[$x])),"d") Then ContinueLoop
        If $dfLIST[$x] = "" Then ContinueLoop
        $fSPLIT = StringSplit($dfLIST[$x],"\")
        If $fSPLIT[0] < $dPOS + 2 Then 
            GUICtrlCreateTreeViewItem(StringStripCR($fSPLIT[$fSPLIT[0]]),$cTree)
        ElseIf $fSPLIT[0] = $dPOS + 2 Then
            GUICtrlCreateTreeViewItem(StringStripCR($fSPLIT[$fSPLIT[0]]),Eval($fSPLIT[$1POS]))
        ElseIf $fSPLIT[0] > $dPOS + 2 Then
            For $z = 1 To $mLEN
                If $fSPLIT[0] = $curDEPTH + $z Then
                    $curDEPTH+=$z
                    $fSPLIT[$curDEPTH] = StringStripCR($fSPLIT[$curDEPTH])
                    GUICtrlCreateTreeViewItem($fSPLIT[$curDEPTH],Eval($fSPLIT[$curDEPTH - 1]))
                    ExitLoop
                EndIf
            Next
        EndIf
    Next    

EndFunc

Func _go()
    _GUICtrlTreeViewDeleteAllItems($cTV1)
    $spath = @StartMenuDir & "\Programs"
    _PathToTreeView($spath,$cTV1)
    GUICtrlSetState($cTV1,$GUI_SHOW)
EndFunc

Let me know what you think, especially if you find a bug.

later,

Sul

Edit: removed further un-needed, add simple TreeView delete for sample purpose

Edited by sulfurious
Link to comment
Share on other sites

When, and if, you click the "button1" button, when the treeview is already filled up, it keeps filling up... Instead you should make it "Refresh" it.

Yeah, I had not decided whether to write that in or not. For my purposes I don't want it in there. I did add a simple delete to the sample script tho.

later,

Sul

Link to comment
Share on other sites

@sulfurious

Dude u are evil i just deciced a hour back to make a script which does the same thing your evil basta.

Btw Nice script, JK

Edited by rambo3889
My Scripts:Radioblog Club Music DownloaderOther stuff:Fun movieIm serious read the help file it helps :PFight 'Till you drop. Never stop, You Cant give up. Til you reach the top Fight! youÂ’re the best in town Fight!
Link to comment
Share on other sites

  • 2 weeks later...

Working on a new version. Not done, but seems much faster so far.

; Test of directory to TreeViewItem
#include <CONSTANTS.AU3>
#include <GUICONSTANTS.AU3>
#include <ARRAY.AU3>

Global $RootDir = ""
Global $aTV_CtrlID[1] = [0]

Opt("GUIOnEventMode", 1)
$hGUI = GUICreate("Path to TreeView Demo", 500, 500, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit", $hGUI)
GUICtrlCreateLabel("Root Directory:", 10, 10, 200, 30)
$Input_1 = GUICtrlCreateInput("", 10, 40, 400, 30)
GUICtrlSetState($Input_1, BitOR(GUICtrlGetState($Input_1), $GUI_DROPACCEPTED))
$Button_1 = GUICtrlCreateButton("...", 420, 45, 40, 20)
GUICtrlSetOnEvent($Button_1, "_PickRoot")
GUICtrlCreateLabel("TreeView of root directory:", 10, 80, 200, 30)
$TreeView_1 = GUICtrlCreateTreeView(10, 110, 480, 330)
$Button_2 = GUICtrlCreateButton("CLEAR", 100, 450, 60, 40)
GUICtrlSetOnEvent($Button_2, "_ClearTree")
$Button_3 = GUICtrlCreateButton("GO", 220, 450, 60, 40)
GUICtrlSetOnEvent($Button_3, "_Go")
$Button_4 = GUICtrlCreateButton("EXIT", 340, 450, 60, 40)
GUICtrlSetOnEvent($Button_4, "_Exit")

GUISetState(@SW_SHOW, $hGUI)

While 1
    Sleep(10)
WEnd



; Function _PickRoot()
;   Selects and sets the root directory from which to search
Func _PickRoot()
    $RootDir = FileSelectFolder("Select to root directory from which to search: ", "", 1 + 4)
    If Not @error Then GUICtrlSetData($Input_1, $RootDir)
EndFunc   ;==>_PickRoot


; Function _ClearTree()
;   Clears the TreeView
Func _ClearTree()
    MsgBox(64, "Debug", "Clear button pushed.", 2)
EndFunc   ;==>_ClearTree


; Function _Go()
;   Executes the search and populates the TreeView
Func _Go()
    If $RootDir = "" Then Return 0
    Local $sDir = "", $PID, $aItems, $sBranchPath, $aPathSplit, $i, $n
    
    ; Read the directory to a string
    Local $ExtCmd = @ComSpec & ' /c DIR /s /b "' & $RootDir & '"'
    $PID = Run($ExtCmd, @TempDir, @SW_MINIMIZE, $STDOUT_CHILD)
    While 1
        $sDir &= StdoutRead($PID)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    
    ; Split the string to an array
    $aItems = StringSplit($sDir, @CRLF, 1)
    
    ; Split each line to isolate item and add to TreeView
    ;   Save control IDs to $aTV_CtrlID array
    For $i = 1 To $aItems[0]
        ; Remove the root path portion of the string
        $sBranchPath = StringReplace($aItems[$i], $RootDir & "\", "")
        $aPathSplit = StringSplit($sBranchPath, "\")
        If $aPathSplit[0] = 1 Then
            ; First level branch from root
            _ArrayAdd($aTV_CtrlID, $sBranchPath & "||" & GUICtrlCreateTreeViewItem($aPathSplit[1], $TreeView_1))
        Else
            ; Sub-branch deeper in tree
            For $n = 1 To UBound($aTV_CtrlID) - 1
                ; Find the parent branch, extract it's Control ID to hang branch from
                
            Next
            
        EndIf
    Next
    
    
    Return 1
EndFunc   ;==>_Go


; Function _Exit()
Func _Exit()
    Exit
EndFunc   ;==>_Exit

:lmao:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Working on a new version. Not done, but seems much faster so far.

; Test of directory to TreeViewItem
#include <CONSTANTS.AU3>
#include <GUICONSTANTS.AU3>
#include <ARRAY.AU3>

Global $RootDir = ""
Global $aTV_CtrlID[1] = [0]

Opt("GUIOnEventMode", 1)
$hGUI = GUICreate("Path to TreeView Demo", 500, 500, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit", $hGUI)
GUICtrlCreateLabel("Root Directory:", 10, 10, 200, 30)
$Input_1 = GUICtrlCreateInput("", 10, 40, 400, 30)
GUICtrlSetState($Input_1, BitOR(GUICtrlGetState($Input_1), $GUI_DROPACCEPTED))
$Button_1 = GUICtrlCreateButton("...", 420, 45, 40, 20)
GUICtrlSetOnEvent($Button_1, "_PickRoot")
GUICtrlCreateLabel("TreeView of root directory:", 10, 80, 200, 30)
$TreeView_1 = GUICtrlCreateTreeView(10, 110, 480, 330)
$Button_2 = GUICtrlCreateButton("CLEAR", 100, 450, 60, 40)
GUICtrlSetOnEvent($Button_2, "_ClearTree")
$Button_3 = GUICtrlCreateButton("GO", 220, 450, 60, 40)
GUICtrlSetOnEvent($Button_3, "_Go")
$Button_4 = GUICtrlCreateButton("EXIT", 340, 450, 60, 40)
GUICtrlSetOnEvent($Button_4, "_Exit")

GUISetState(@SW_SHOW, $hGUI)

While 1
    Sleep(10)
WEnd
; Function _PickRoot()
;   Selects and sets the root directory from which to search
Func _PickRoot()
    $RootDir = FileSelectFolder("Select to root directory from which to search: ", "", 1 + 4)
    If Not @error Then GUICtrlSetData($Input_1, $RootDir)
EndFunc   ;==>_PickRoot
; Function _ClearTree()
;   Clears the TreeView
Func _ClearTree()
    MsgBox(64, "Debug", "Clear button pushed.", 2)
EndFunc   ;==>_ClearTree
; Function _Go()
;   Executes the search and populates the TreeView
Func _Go()
    If $RootDir = "" Then Return 0
    Local $sDir = "", $PID, $aItems, $sBranchPath, $aPathSplit, $i, $n
    
    ; Read the directory to a string
    Local $ExtCmd = @ComSpec & ' /c DIR /s /b "' & $RootDir & '"'
    $PID = Run($ExtCmd, @TempDir, @SW_MINIMIZE, $STDOUT_CHILD)
    While 1
        $sDir &= StdoutRead($PID)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    
    ; Split the string to an array
    $aItems = StringSplit($sDir, @CRLF, 1)
    
    ; Split each line to isolate item and add to TreeView
    ;   Save control IDs to $aTV_CtrlID array
    For $i = 1 To $aItems[0]
        ; Remove the root path portion of the string
        $sBranchPath = StringReplace($aItems[$i], $RootDir & "\", "")
        $aPathSplit = StringSplit($sBranchPath, "\")
        If $aPathSplit[0] = 1 Then
            ; First level branch from root
            _ArrayAdd($aTV_CtrlID, $sBranchPath & "||" & GUICtrlCreateTreeViewItem($aPathSplit[1], $TreeView_1))
        Else
            ; Sub-branch deeper in tree
            For $n = 1 To UBound($aTV_CtrlID) - 1
                ; Find the parent branch, extract it's Control ID to hang branch from
                
            Next
            
        EndIf
    Next
    
    
    Return 1
EndFunc   ;==>_Go
; Function _Exit()
Func _Exit()
    Exit
EndFunc   ;==>_Exit

:lmao:

I am not sure that it makes a difference - but it would be cool to be able go up a directory rather than using the tiddely (sp)

2¢

All by me:

"Sometimes you have to go back to where you started, to get to where you want to go." 

"Everybody catches up with everyone, eventually" 

"As you teach others, you are really teaching yourself."

From my dad

"Do not worry about yesterday, as the only thing that you can control is tomorrow."

 

WindowsError.gif

WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF

AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send

StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2

AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit  Docs

SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF

Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language

Programming Tips

Excel Changes

ControlHover.UDF

GDI_Plus

Draw_On_Screen

GDI Basics

GDI_More_Basics

GDI Rotate

GDI Graph

GDI  CheckExistingItems

GDI Trajectory

Replace $ghGDIPDll with $__g_hGDIPDll

DLL 101?

Array via Object

GDI Swimlane

GDI Plus French 101 Site

GDI Examples UEZ

GDI Basic Clock

GDI Detection

Ternary operator

Link to comment
Share on other sites

Have you tested it on C:\Documents and Settings - it takes a very long time - also drill to C:\Documents and Settings\Default User\Local Settings - and see what happens? After drilling to first C:\Documents and Settings and then C:\Documents and Settings\Default User\Local Settings you get a temp directory. If you run C:\Documents and Settings\Default User\Local Settings first you also get just the temp directory, but one time I got a listing of other directories - not sure what I did or even if it was the same user :lmao:

Also there is a bug that if you pick a path and then change your mind before clicking go - it hangs for long time, not sure if not forever - also I tried pasting the path and it hung as well. Maybe add: text box when searching for the path?

2¢

All by me:

"Sometimes you have to go back to where you started, to get to where you want to go." 

"Everybody catches up with everyone, eventually" 

"As you teach others, you are really teaching yourself."

From my dad

"Do not worry about yesterday, as the only thing that you can control is tomorrow."

 

WindowsError.gif

WIKI | Tabs; | Arrays; | Strings | Wiki Arrays | How to ask a Question | Forum Search | FAQ | Tutorials | Original FAQ | ONLINE HELP | UDF's Wiki | AutoIt PDF

AutoIt Snippets | Multple Guis | Interrupting a running function | Another Send

StringRegExp | StringRegExp Help | RegEXTester | REG TUTOR | Reg TUTOT 2

AutoItSetOption | Macros | AutoIt Snippets | Wrapper | Autoit  Docs

SCITE | SciteJump | BB | MyTopics | Programming | UDFs | AutoIt 123 | UDFs Form | UDF

Learning to script | Tutorials | Documentation | IE.AU3 | Games? | FreeSoftware | Path_Online | Core Language

Programming Tips

Excel Changes

ControlHover.UDF

GDI_Plus

Draw_On_Screen

GDI Basics

GDI_More_Basics

GDI Rotate

GDI Graph

GDI  CheckExistingItems

GDI Trajectory

Replace $ghGDIPDll with $__g_hGDIPDll

DLL 101?

Array via Object

GDI Swimlane

GDI Plus French 101 Site

GDI Examples UEZ

GDI Basic Clock

GDI Detection

Ternary operator

Link to comment
Share on other sites

Yes I did test it for large directories. Unfortunately, the whole array is looping itself inside itself for the duration of itself. I knew it would be extremely slow for large directories, but it is fast for it intended purpose of showing the contents of one small directory.

I will look at the bug you described. I have the routine in a project I am working on, but have not tried to break it yet. I will soon though.

I will try out PS's version as well, could always be faster.

Sul

Edited by sulfurious
Link to comment
Share on other sites

Fully functional now, but still too sloooowwwwww if Depth > 2. My Documents and Settings on the test machine has 22678 objects under it. Took 22.2sec to create a fresh TreeView with Depth=1, 33.7sec with Depth=2 and 275.8sec :lmao: with Depth=3.

First thing I want to do to speed it up is reduce the amount of searching through the array to find the parent. I should be able to short circuit some of that with some extra logic.

; Test of directory to TreeViewItem
#include <CONSTANTS.AU3>
#include <GUICONSTANTS.AU3>
#include <ARRAY.AU3>
#Include <GuiTreeView.au3>

Global $RootDir = "", $aTV_Items[1][5]

Opt("GUIOnEventMode", 1)
$hGUI = GUICreate("Path to TreeView Demo", 500, 500, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit", $hGUI)
GUICtrlCreateLabel("Root Directory:", 10, 10, 200, 30)
$Input_1 = GUICtrlCreateInput("", 10, 40, 300, 30)
GUICtrlSetState($Input_1, BitOR(GUICtrlGetState($Input_1), $GUI_DROPACCEPTED))
GUICtrlCreateLabel("Depth:", 400, 10, 80, 30)
$Input_2 = GUICtrlCreateInput(2, 400, 40, 70, 30)
GUICtrlCreateUpdown($Input_2)
$Button_1 = GUICtrlCreateButton("...", 320, 45, 40, 20)
GUICtrlSetOnEvent($Button_1, "_PickRoot")
GUICtrlCreateLabel("TreeView of root directory:", 10, 80, 200, 30)
$TreeView_1 = GUICtrlCreateTreeView(10, 110, 480, 330)
$Button_2 = GUICtrlCreateButton("CLEAR", 100, 450, 60, 40)
GUICtrlSetOnEvent($Button_2, "_ClearTree")
$Button_3 = GUICtrlCreateButton("GO", 220, 450, 60, 40)
GUICtrlSetOnEvent($Button_3, "_Go")
$Button_4 = GUICtrlCreateButton("EXIT", 340, 450, 60, 40)
GUICtrlSetOnEvent($Button_4, "_Exit")

GUISetState(@SW_SHOW, $hGUI)

While 1
    Sleep(10)
WEnd



; Function _PickRoot()
;   Selects and sets the root directory from which to search
Func _PickRoot()
    $RootDir = FileSelectFolder("Select to root directory from which to search: ", "", 1 + 4)
    If Not @error Then GUICtrlSetData($Input_1, $RootDir)
EndFunc   ;==>_PickRoot


; Function _ClearTree()
;   Clears the TreeView
Func _ClearTree()
    ; Put up working message GUI
    Local $aWinPos = WinGetPos("Path to TreeView Demo")
    Local $hWorkingGUI = GUICreate("Path to TreeView Demo", 500, 100, $aWinPos[0] + 25, $aWinPos[1] + 25)
    Local $Label_Working = GUICtrlCreateLabel("Working... Clearing TreeView", 10, 10, 480, 80)
    GUISetState(@SW_SHOW, $hWorkingGUI)
    _GUICtrlTreeViewDeleteAllItems($TreeView_1)
    Dim $aTV_Items[1][5]
    GUIDelete($hWorkingGUI)
EndFunc   ;==>_ClearTree


; Function _Go()
;   Executes the search and populates the TreeView
Func _Go()
    If UBound($aTV_Items) > 1 Then _ClearTree()
    Local $DebugTimer = TimerInit()
    If $RootDir = "" Then Return 0
    Local $sDir = "", $PID, $aItems, $sBranchPath, $aPathSplit, $i, $b
    
    ; Put up working message GUI
    Local $aWinPos = WinGetPos("Path to TreeView Demo")
    Local $hWorkingGUI = GUICreate("Path to TreeView Demo", 500, 100, $aWinPos[0] + 50, $aWinPos[1] + 50)
    Local $Label_Working = GUICtrlCreateLabel("Working... Getting directory listing of:" & @CRLF & $RootDir, 10, 10, 480, 80)
    GUISetState(@SW_SHOW, $hWorkingGUI)
    
    ; Establish depth to display from 1 to 8
    Local $iDepth = Number(GUICtrlRead($Input_2))
    If $iDepth < 1 Then $iDepth = 1
    If $iDepth > 8 Then $iDepth = 8
    GUICtrlSetData($Input_2, $iDepth)
    
    ; Read the directory to a string
    Local $ExtCmd = @ComSpec & ' /c DIR /s /b "' & $RootDir & '"'
    $PID = Run($ExtCmd, @TempDir, @SW_MINIMIZE, $STDOUT_CHILD)
    While 1
        $sDir &= StdoutRead($PID)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    
    ; Split the string to an array
    GUICtrlSetData($Label_Working, "Working... Adding items to TreeView")
    $aDirSplit = StringSplit($sDir, @CRLF, 1)
    
    ; Split each line to isolate item and add to TreeView items array:
    ;   $aTV_Items[0][0] = Count
    ;   $aTV_Items[n][0] = BranchPath from root dir
    ;   $aTV_Items[n][1] = Display text for TreeViewItem
    ;   $aTV_Items[n][2] = Depth (1 = first level of TreeViewItems)
    ;   $aTV_Items[n][3] = Array index of parent (N/A if depth = 1)
    ;   $aTV_Items[n][4] = CtrlID of this TreeViewItem
    Dim $aTV_Items[$aDirSplit[0] + 1][5]
    
    ; Set data for root dir path at index 0
    $aTV_Items[0][0] = $aDirSplit[0] ; Count of total items to list
    $aTV_Items[0][1] = "{Root Dir}" ; Display text for root dir
    $aTV_Items[0][4] = $TreeView_1 ; Control ID of main TreeView
    
    For $i = 1 To $aDirSplit[0]
        ; Remove the root path portion of the string and save to $aTV_Items[n][0]
        $aTV_Items[$i][0] = StringReplace($aDirSplit[$i], $RootDir & "\", "")
        GUICtrlSetData($Label_Working, "Working... Adding item " & $i & " of " & $aDirSplit[0] & ":" & @CRLF & $aTV_Items[$i][0])
        
        ; Split path to component parts
        $aPathSplit = StringSplit($aTV_Items[$i][0], "\")
        
        ; Get last portion for display and save to $aTV_Items[n][1]
        $aTV_Items[$i][1] = $aPathSplit[$aPathSplit[0]]
        
        ; Save relative path depth to $aTV_[n][2] (1 = first level of TreeViewItems)
        $aTV_Items[$i][2] = $aPathSplit[0]
        
        ; Find and save parent's array index to $aTV_Items[n][3]
        ;   If first level branch from root path, parent index is 0
        $aTV_Items[$i][3] = 0
        If $aPathSplit[0] > 1 And $aPathSplit[0] <= $iDepth Then
            ; Find parent in by searching array in reverse
            $iBckSlash = StringInStr($aTV_Items[$i][0], "\", 0, -1) ; Right-most backslash
            $sParentPath = StringLeft($aTV_Items[$i][0], $iBckSlash - 1)
            For $b = $i To 1 Step - 1
                If $aTV_Items[$b][0] = $sParentPath Then
                    $aTV_Items[$i][3] = $b
                    ExitLoop
                EndIf
            Next
        EndIf
        
        ; Create TreeViewItem, saving CtrlID to $aTV_Items[n][4]
        If $aPathSplit[0] <= $iDepth Then $aTV_Items[$i][4] = GUICtrlCreateTreeViewItem($aTV_Items[$i][1], $aTV_Items[$aTV_Items[$i][3]][4])
    Next
    $DebugTimer = TimerDiff($DebugTimer)
    GUICtrlSetData($Label_Working, "Working... Done updating TreeView" & @CRLF & "Time = " & $DebugTimer / 1000 & " seconds")
    Sleep(3000)
    GUIDelete($hWorkingGUI)
    Return 1
EndFunc   ;==>_Go


; Function _Exit()
Func _Exit()
    Exit
EndFunc   ;==>_Exit

:ph34r:

@sulfurious: At least thar' aint none o' that godless communist Assign()/Eval() in it! :geek:

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

First speed up... short circuited the search for the parent where the directory depth has not changed (re-use previous parent). The time for Depth=1 is still 22.2sec, but the time for Depth=2 dropped to 22.7, and Depth=3 dropped from 275 to only 93.7! :ph34r:

Can a brother get a Woot! Woot! :lmao:

; Test of directory to TreeViewItem
#include <CONSTANTS.AU3>
#include <GUICONSTANTS.AU3>
#include <ARRAY.AU3>
#Include <GuiTreeView.au3>

Global $RootDir = "", $aTV_Items[1][5]

Opt("GUIOnEventMode", 1)
$hGUI = GUICreate("Path to TreeView Demo", 500, 500, -1, -1, -1, $WS_EX_ACCEPTFILES)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit", $hGUI)
GUICtrlCreateLabel("Root Directory:", 10, 10, 200, 30)
$Input_1 = GUICtrlCreateInput("", 10, 40, 300, 30)
GUICtrlSetState($Input_1, BitOR(GUICtrlGetState($Input_1), $GUI_DROPACCEPTED))
GUICtrlCreateLabel("Depth:", 400, 10, 80, 30)
$Input_2 = GUICtrlCreateInput(2, 400, 40, 70, 30)
GUICtrlCreateUpdown($Input_2)
$Button_1 = GUICtrlCreateButton("...", 320, 45, 40, 20)
GUICtrlSetOnEvent($Button_1, "_PickRoot")
GUICtrlCreateLabel("TreeView of root directory:", 10, 80, 200, 30)
$TreeView_1 = GUICtrlCreateTreeView(10, 110, 480, 330)
$Button_2 = GUICtrlCreateButton("CLEAR", 100, 450, 60, 40)
GUICtrlSetOnEvent($Button_2, "_ClearTree")
$Button_3 = GUICtrlCreateButton("GO", 220, 450, 60, 40)
GUICtrlSetOnEvent($Button_3, "_Go")
$Button_4 = GUICtrlCreateButton("EXIT", 340, 450, 60, 40)
GUICtrlSetOnEvent($Button_4, "_Exit")

GUISetState(@SW_SHOW, $hGUI)

While 1
    Sleep(10)
WEnd



; Function _PickRoot()
;   Selects and sets the root directory from which to search
Func _PickRoot()
    $RootDir = FileSelectFolder("Select to root directory from which to search: ", "", 1 + 4)
    If Not @error Then GUICtrlSetData($Input_1, $RootDir)
EndFunc   ;==>_PickRoot


; Function _ClearTree()
;   Clears the TreeView
Func _ClearTree()
    ; Put up working message GUI
    Local $aWinPos = WinGetPos("Path to TreeView Demo")
    Local $hWorkingGUI = GUICreate("Path to TreeView Demo", 500, 100, $aWinPos[0] + 25, $aWinPos[1] + 25)
    Local $Label_Working = GUICtrlCreateLabel("Working... Clearing TreeView", 10, 10, 480, 80)
    GUISetState(@SW_SHOW, $hWorkingGUI)
    _GUICtrlTreeViewDeleteAllItems($TreeView_1)
    Dim $aTV_Items[1][5]
    GUIDelete($hWorkingGUI)
    Return
EndFunc   ;==>_ClearTree


; Function _Go()
;   Executes the search and populates the TreeView
Func _Go()
    If UBound($aTV_Items) > 1 Then _ClearTree()
    Local $DebugTimer = TimerInit()
    If $RootDir = "" Then Return 0
    Local $sDir = "", $PID, $aItems, $sBranchPath, $aPathSplit, $i, $b
    Local $iLastDepth = "", $iLastParent = ""
    
    ; Put up working message GUI
    Local $aWinPos = WinGetPos("Path to TreeView Demo")
    Local $hWorkingGUI = GUICreate("Path to TreeView Demo", 500, 100, $aWinPos[0] + 50, $aWinPos[1] + 50)
    Local $Label_Working = GUICtrlCreateLabel("Working... Getting directory listing of:" & @CRLF & $RootDir, 10, 10, 480, 80)
    GUISetState(@SW_SHOW, $hWorkingGUI)
    
    ; Establish depth to display from 1 to 8
    Local $iDepth = Number(GUICtrlRead($Input_2))
    If $iDepth < 1 Then $iDepth = 1
    If $iDepth > 8 Then $iDepth = 8
    GUICtrlSetData($Input_2, $iDepth)
    
    ; Read the directory to a string
    Local $ExtCmd = @ComSpec & ' /c DIR /s /b "' & $RootDir & '"'
    $PID = Run($ExtCmd, @TempDir, @SW_MINIMIZE, $STDOUT_CHILD)
    While 1
        $sDir &= StdoutRead($PID)
        If @error Then ExitLoop
        Sleep(10)
    WEnd
    
    ; Split the string to an array
    GUICtrlSetData($Label_Working, "Working... Adding items to TreeView")
    $aDirSplit = StringSplit($sDir, @CRLF, 1)
    
    ; Split each line to isolate item and add to TreeView items array:
    ;   $aTV_Items[0][0] = Count
    ;   $aTV_Items[n][0] = BranchPath from root dir
    ;   $aTV_Items[n][1] = Display text for TreeViewItem
    ;   $aTV_Items[n][2] = Depth (1 = first level of TreeViewItems)
    ;   $aTV_Items[n][3] = Array index of parent (N/A if depth = 1)
    ;   $aTV_Items[n][4] = CtrlID of this TreeViewItem
    Dim $aTV_Items[$aDirSplit[0] + 1][5]
    
    ; Set data for root dir path at index 0
    $aTV_Items[0][0] = $aDirSplit[0] ; Count of total items to list
    $aTV_Items[0][1] = "{Root Dir}" ; Display text for root dir
    $aTV_Items[0][4] = $TreeView_1 ; Control ID of main TreeView
    
    For $i = 1 To $aDirSplit[0]
        ; Remove the root path portion of the string and save to $aTV_Items[n][0]
        $aTV_Items[$i][0] = StringReplace($aDirSplit[$i], $RootDir & "\", "")
        GUICtrlSetData($Label_Working, "Working... Adding item " & $i & " of " & $aDirSplit[0] & ":" & @CRLF & $aTV_Items[$i][0])
        
        ; Split path to component parts
        $aPathSplit = StringSplit($aTV_Items[$i][0], "\")
        
        ; Get last portion for display and save to $aTV_Items[n][1]
        $aTV_Items[$i][1] = $aPathSplit[$aPathSplit[0]]
        
        ; Save relative path depth to $aTV_[n][2] (1 = first level of TreeViewItems)
        $aTV_Items[$i][2] = $aPathSplit[0]
        
        ; Find and save parent's array index to $aTV_Items[n][3]
        ;   If first level branch from root path, parent index is 0
        Select
            Case $aTV_Items[$i][2] = $iLastDepth
                ; Depth has not changed, re-use parent
                $aTV_Items[$i][3] = $iLastParent
                
            Case $aTV_Items[$i][2] = 1
                ; first level from root
                $aTV_Items[$i][3] = 0
                
            Case $aPathSplit[0] <= $iDepth
                ; Find parent in by searching array in reverse
                $iBckSlash = StringInStr($aTV_Items[$i][0], "\", 0, -1) ; Right-most backslash
                $sParentPath = StringLeft($aTV_Items[$i][0], $iBckSlash - 1)
                For $b = $i - 1 To 1 Step - 1
                    If $aTV_Items[$b][0] = $sParentPath Then
                        $aTV_Items[$i][3] = $b
                        ; Save last used values for re-use
                        $iLastDepth = $aTV_Items[$i][2]
                        $iLastParent = $aTV_Items[$i][3]
                        ExitLoop
                    EndIf
                Next
        EndSelect
        
        ; Create TreeViewItem, saving CtrlID to $aTV_Items[n][4]
        If $aPathSplit[0] <= $iDepth Then $aTV_Items[$i][4] = GUICtrlCreateTreeViewItem($aTV_Items[$i][1], $aTV_Items[$aTV_Items[$i][3]][4])
    Next
    $DebugTimer = TimerDiff($DebugTimer)
    GUICtrlSetData($Label_Working, "Working... Done updating TreeView" & @CRLF & "Time = " & $DebugTimer / 1000 & " seconds")
    Sleep(3000)
    GUIDelete($hWorkingGUI)
    Return 1
EndFunc   ;==>_Go


; Function _Exit()
Func _Exit()
    Exit
EndFunc   ;==>_Exit

:geek:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

This looks really nice! Very good job!

Thanks. :ph34r:

The speed is still disappointing. My next revision will be much faster because it will break the process into two TreeViews, one for directories and one for files in the selected directory. It's the massive list of files in directories like "Temporary Internet Files" that chokes it, not the directories. :lmao:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

The speed is still disappointing. My next revision will be much faster because it will break the process into two TreeViews, one for directories and one for files in the selected directory. It's the massive list of files in directories like "Temporary Internet Files" that chokes it, not the directories. :lmao:

This looks interesting... something I will have to do one of these days. Though one treeview would probably be more elegant for what I have in mind.

Re speed: did you look into the UDF for traversing a directory tree I wrote a couple of weeks ago? This is a little slower than the Run/Comspec/dir /s method but OTOH this will deliver the files and directories ready for "immediate consumption" and is much more flexible as well. Even if this should turn out to be not perfect for your purpose the code might give you some ideas.

Or perhaps I should try to graft your code onto mine :ph34r:

Link to comment
Share on other sites

I've been waiting for someone to make a folder structure into treeview. This is perfect! Thanks!

How do you get the selected files full path?

Woot! Woot!

:ph34r::geek::)

Be warned, I see a bug. There's a mangled pointer in the Array refs somewhere, and sub-branches are being added in the wrong place. Work intrudes, and I can't work on it right now, but will post with fix when I can.

:ph34r::);)

The demo was only about timing how long it took to populate the TreeView, so I didn't include using it for anything. All you would have to do is get the selected TreeViewItem control ID with GuiCtrlRead($TreeView_1), then a For/Next loop to find that control ID in the array and read out the path from it.

:lmao:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

LOL, Poof! is exactly what it does for one small directory, which is exactly what I built it to do. Actually it was built soley for creating a [ProfileItems] section in an INF file, to open the start menu directory and show it's contents. Had I known there was a need for an AutoIt 'Explorer' shell, I would have concentrated more on traversing the entire harddrive.

I had the same problem PS, with the bug you spoke of where sub-branches are being screwed. That is why mine is slow, I think, because I purposefully built it to get rid of that bug. I have not tested it on too much, it does what I need it to. But I am curious now to see if I can get the whole drive. I have some ideas on that..

later.

Sul

Link to comment
Share on other sites

Probably a good time to point you all towards Holger's AutoItExplorer. Use it for inspiration and "code ripoff" :lmao:

To run it with the latest beta (3.2.1.8) I hae commented out some of the Global Const declarations that are now part of GUIConstants.au3

#include <GUIConstants.au3>
#include <GUITreeView.au3>
#include <Misc.au3>
#cs
; TV functions
Global Const $TVM_INSERTITEM            = $TV_FIRST + 0
Global Const $TVM_GETITEMRECT           = $TV_FIRST + 4
Global Const $TVM_SETIMAGELIST          = $TV_FIRST + 9
Global Const $TVM_SETITEM               = $TV_FIRST + 13
Global Const $TVM_HITTEST               = $TV_FIRST + 17

Global Const $TVI_FIRST                 = 0xFFFF0001

; Masks
Global Const $TVIF_IMAGE                = 0x0002
Global Const $TVIF_HANDLE               = 0x0010
Global Const $TVIF_SELECTEDIMAGE        = 0x0020
Global Const $TVIF_CHILDREN             = 0x0040

; States
Global Const $TVIS_CUT                  = 0x0004
Global Const $TVIS_DROPHILITED          = 0x0008
Global Const $TVIS_BOLD                 = 0x0010
Global Const $TVIS_EXPANDED             = 0x0020

; Relationship/specific item
Global Const $TVGN_ROOT                 = 0x0000
Global Const $TVGN_PREVIOUS             = 0x0002
Global Const $TVGN_FIRSTVISIBLE         = 0x0005
Global Const $TVGN_NEXTVISIBLE          = 0x0006
Global Const $TVGN_PREVIOUSVISIBLE      = 0x0007
Global Const $TVGN_DROPHILITE           = 0x0008

; Hittest infos
Global Const $TVHT_NOWHERE              = 0x0001
Global Const $TVHT_ONITEMICON           = 0x0002
Global Const $TVHT_ONITEMLABEL          = 0x0004
Global Const $TVHT_ONITEMINDENT         = 0x0008
Global Const $TVHT_ONITEMBUTTON         = 0x0010
Global Const $TVHT_ONITEMRIGHT          = 0x0020
Global Const $TVHT_ONITEMSTATEICON      = 0x0040
Global Const $TVHT_ONITEM               = BitOr($TVHT_ONITEMICON, $TVHT_ONITEMLABEL, $TVHT_ONITEMSTATEICON)
Global Const $TVHT_ABOVE                = 0x0100
Global Const $TVHT_BELOW                = 0x0200
Global Const $TVHT_TORIGHT              = 0x0400
Global Const $TVHT_TOLEFT               = 0x0800

If Not IsDeclared("LVM_SETEXTENDEDLISTVIEWSTYLE")   Then Global Const $LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036
If Not IsDeclared("LVM_SETCOLUMN")                  Then Global Const $LVM_SETCOLUMN                = 0x101A
If Not IsDeclared("LVCF_FMT")                       Then Global Const $LVCF_FMT                     = 0x0001
If Not IsDeclared("LVCFMT_RIGHT")                   Then Global Const $LVCFMT_RIGHT                 = 0x0001
If Not IsDeclared("LVM_GETHEADER")                  Then Global Const $LVM_GETHEADER                = 0x101F
#ce
Global Const $TVM_HITTEST               = $TV_FIRST + 17

Global Const $TVHT_ONITEMICON           = 0x0002
Global Const $TVHT_ONITEMLABEL          = 0x0004
Global Const $TVHT_ONITEMINDENT         = 0x0008
Global Const $TVHT_ONITEMBUTTON         = 0x0010
Global Const $TVHT_ONITEMRIGHT          = 0x0020
Global Const $TVHT_ONITEMSTATEICON      = 0x0040
Global Const $TVHT_ONITEM               = BitOr($TVHT_ONITEMICON, $TVHT_ONITEMLABEL, $TVHT_ONITEMSTATEICON)
Edited by Uten
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...