Kanashius Posted July 14, 2015 Posted July 14, 2015 (edited) This is a UDF to use a Listview or Treeview as a File/Folder Explorer. It allows to create a system, where a root folder can be set and that synchronizes all attached Tree or Listviews. So it is possible to attach multiple views to one system. The following functions are available: ; #CURRENT# ===================================================================================================================== ; __TreeListExplorer_StartUp ; __TreeListExplorer_Shutdown ; __TreeListExplorer_CreateSystem ; __TreeListExplorer_DeleteSystem ; __TreeListExplorer_AddView ; __TreeListExplorer_RemoveView ; __TreeListExplorer_OpenPath ; __TreeListExplorer_GetPath ; __TreeListExplorer_GetRoot ; __TreeListExplorer_SetRoot ; =============================================================================================================================== When creating a System, a callback function can be provided to be called, when the root folder or the current folder changes. When adding a View, callback functions for single/double click at an item as well as a loading callback can be added. Example view: Spoiler The Code for the Example to get a quick overview: Spoiler expandcollapse popup#include "TreeListExplorer.au3" #include <GuiTreeView.au3> Global $iWidth = 1600, $iHeight = 1000, $iSpace = 5 ; StartUp of the TreeListExplorer UDF (required) __TreeListExplorer_StartUp() If @error Then ConsoleWrite("__TreeListExplorer_StartUp failed: "&@error&":"&@extended&@crlf) ; create gui Local $hGui = GUICreate("TreeListExplorer Example", $iWidth, $iHeight) Local $iTopLine = 100 Local $iCtrlHeight = ($iHeight - $iTopLine)/2 - $iSpace*3, $iCtrlWidth = $iWidth/2 - $iSpace*3 ; create left gui Local $iTop = $iSpace*2+$iTopLine, $iLeft = $iSpace Local $hTreeViewLeft = GUICtrlCreateTreeView($iLeft, $iTop, $iCtrlWidth, $iCtrlHeight) $iTop+=$iCtrlHeight+$iSpace Local $hListViewLeft = GUICtrlCreateListView("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight) ; create right gui Local $iLeft = $iSpace*2 + $iCtrlWidth Local $iTop = $iSpace GUICtrlCreateLabel("Current Folder:", $iLeft, $iTop, 75, 20) Local $hLabelCurrentFolderRight = GUICtrlCreateLabel("", $iLeft+75, $iTop, $iCtrlWidth-75, 20) Local $hProgressRight = GUICtrlCreateProgress($iLeft, $iTop+20+$iSpace, $iCtrlWidth, 20) Local $iTop = $iSpace*2+$iTopLine Local $hTreeViewRight = GUICtrlCreateTreeView($iLeft, $iTop, $iCtrlWidth, $iCtrlHeight) $iTop+=$iCtrlHeight+$iSpace Local $hListViewRight = GUICtrlCreateListView("", $iLeft, $iTop, $iCtrlWidth, $iCtrlHeight) ; Create TLE system for the left side Local $hTLESystemLeft = __TreeListExplorer_CreateSystem($hGui) If @error Then ConsoleWrite("__TreeListExplorer_CreateSystem failed: "&@error&":"&@extended&@crlf) ; Add Views to TLE system __TreeListExplorer_AddView($hTLESystemLeft, $hTreeViewLeft) If @error Then ConsoleWrite("__TreeListExplorer_AddView $hTreeView failed: "&@error&":"&@extended&@crlf) __TreeListExplorer_AddView($hTLESystemLeft, $hListViewLeft) If @error Then ConsoleWrite("__TreeListExplorer_AddView $hListView failed: "&@error&":"&@extended&@crlf) ; Create TLE system for the right side Local $hTLESystemRight = __TreeListExplorer_CreateSystem($hGui, "", "_currentFolder") If @error Then ConsoleWrite("__TreeListExplorer_CreateSystem failed: "&@error&":"&@extended&@crlf) ; Add Views to TLE system: ShowFolders=True, ShowFiles=True __TreeListExplorer_AddView($hTLESystemRight, $hTreeViewRight, True, True, "_clickCallback", "_doubleClickCallback", "_loadingCallback", "_selectCallback") If @error Then ConsoleWrite("__TreeListExplorer_AddView $hTreeView failed: "&@error&":"&@extended&@crlf) __TreeListExplorer_AddView($hTLESystemRight, $hListViewRight, True, True, "_clickCallback", "_doubleClickCallback", "_loadingCallback", "_selectCallback") If @error Then ConsoleWrite("__TreeListExplorer_AddView $hListView failed: "&@error&":"&@extended&@crlf) ; Set the root directory for the right side to the users directory __TreeListExplorer_SetRoot($hTLESystemRight, "C:\Users") If @error Then ConsoleWrite("__TreeListExplorer_SetRoot failed: "&@error&":"&@extended&@crlf) ; Open the User profile on the right side __TreeListExplorer_OpenPath($hTLESystemRight, @UserProfileDir) If @error Then ConsoleWrite("__TreeListExplorer_OpenPath failed: "&@error&":"&@extended&@crlf) GUISetState(@SW_SHOW) ConsoleWrite("Left root: "&__TreeListExplorer_GetRoot($hTLESystemLeft)&" Left folder: "&__TreeListExplorer_GetPath($hTLESystemLeft)&@crlf) ConsoleWrite("Right root: "&__TreeListExplorer_GetRoot($hTLESystemRight)&" Right folder: "&__TreeListExplorer_GetPath($hTLESystemRight)&@crlf) ; Removes the TLE system and clears the Tree/Listview ; __TreeListExplorer_DeleteSystem($hTLESystemLeft) ; __TreeListExplorer_RemoveView($hTreeViewRight) while True Local $iMsg = GUIGetMsg() If $iMsg=-3 Then __TreeListExplorer_Shutdown() Exit EndIf WEnd Func _currentFolder($hSystem, $sRoot, $sFolder) GUICtrlSetData($hLabelCurrentFolderRight, $sRoot&$sFolder) ; ConsoleWrite("Current folder in system "&$hSystem&": "&$sRoot&$sFolder&@CRLF) EndFunc Func _selectCallback($hSystem, $hView, $sRoot, $sFolder) ConsoleWrite("Select at "&$hView&": "&$sRoot&$sFolder&@CRLF) EndFunc Func _clickCallback($hSystem, $hView, $sRoot, $sFolder) ConsoleWrite("Click at "&$hView&": "&$sRoot&$sFolder&@CRLF) EndFunc Func _doubleClickCallback($hSystem, $hView, $sRoot, $sFolder) ConsoleWrite("Double click at "&$hView&": "&$sRoot&$sFolder&@CRLF) EndFunc Func _loadingCallback($hSystem, $hView, $sRoot, $sFolder, $bLoading) If $bLoading Then Switch $hView Case GUICtrlGetHandle($hTreeViewLeft) ToolTip("Load TreeView: "&$sRoot&$sFolder) ConsoleWrite("Load: "&$hView&" >> "&$sRoot&$sFolder&@crlf) Case GUICtrlGetHandle($hListViewLeft) ToolTip("Load ListView: "&$sRoot&$sFolder) ConsoleWrite("Load: "&$hView&" >> "&$sRoot&$sFolder&@crlf) Case GUICtrlGetHandle($hListViewRight), GUICtrlGetHandle($hTreeViewRight) GUICtrlSetData($hProgressRight, 50) EndSwitch Else Switch $hView Case GUICtrlGetHandle($hListViewRight), GUICtrlGetHandle($hTreeViewRight) GUICtrlSetData($hProgressRight, 0) EndSwitch ToolTip("") ConsoleWrite("Done: "&$hView&" >> "&$sRoot&$sFolder&@crlf) EndIf EndFunc If you like it, please leave me a comment, also if you have any suggestions to make it better or if you found bugs. I did a complete rework of this UDF (2025/03/02). Now it is easier to use and does not need external UDFs anymore. This also removes a lot of bugs, that were in the old version. It is also possible to freely select if folders and/or files should be visible in any view. The OLD UDF is still available here: FileExplorerTreeAndListview_source.zip Changelog: Version 1.0.0 (Old Version) Version 2.0.0 (New Version after rework) Version 2.1.0 - Rename $sCallbackOnSelect to $sCallbackOnClick - Add an additional callback $sCallbackOnSelectionChange, that is called whenever the Tree-/ListView item selection changes Version 2.2.0 - Improve loading speed for TreeView folders when expanding TreeListExplorer-Example.au3 TreeListExplorer.au3 Edited 4 hours ago by Kanashius rework update My Website: Kanashius Webside (Some of my Programs you can find there)
Danyfirex Posted July 14, 2015 Posted July 14, 2015 Really nice and useful. Thanks for sharing.Saludos Danysys.com AutoIt... UDFs: VirusTotal API 2.0 UDF - libZPlay UDF - Apps: Guitar Tab Tester - VirusTotal Hash Checker Examples: Text-to-Speech ISpVoice Interface - Get installed applications - Enable/Disable Network connection PrintHookProc - WINTRUST - Mute Microphone Level - Get Connected NetWorks - Create NetWork Connection ShortCut
WildByDesign Posted February 25 Posted February 25 On 7/14/2015 at 6:17 AM, Kanashius said: If you like it, please leave me a comment, also if you have any suggestions to make it better or if you found bugs. Thank you for this fantastic UDF. I am honestly quite surprised that it hasn't gotten more attention over the years. Great coding, great example, commenting, etc. AutoItObject needed to be updated to 1.2.8.3 for 64-bit support. That is all good now. I do have one question and wondering if you can help me. I am using only treeview and wish to have the treeview show both folders and files. In the __TLE_DirInTree() function: While 1 $path=FileFindNextFile($search) ;msgbox(48,"",$path) if @extended then if $hItem=-1 then $hItemNew=_GUICtrlTreeView_Add($Tree,0,$path,0,0) else $hItemNew=_GUICtrlTreeView_AddChild($Tree,$hItem,$path,0,0) endif if $SearchAll then if not __TLE_DirInTree($sSearchPath & "\" & $path,$Tree,$hItemNew,false) then _GUICtrlTreeView_Delete($Tree,$hItemNew) if $hItem=-1 then $hItemNew=_GUICtrlTreeView_AddChild($Tree,0,$path,0,0) else $hItemNew=_GUICtrlTreeView_AddChild($Tree,$hItem,$path,0,0) endif endif endif $ChildDirs=true endif if @error=1 then ExitLoop 1 endif WEnd From other examples in the forum: ; Check if a folder If @extended Then ; If so then call the function recursively ListFiles_ToTreeView($sSourceFolder & $sFile, _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sFile)) Else ; If a file than write path and name _GUICtrlTreeView_AddChild($hTreeView, $hItem, $sFile) EndIf However, I have tried for several days now to add the extra Else statement to your UDF in many various ways but all have failed. It is far above my knowledge and experience.
WildByDesign Posted February 25 Posted February 25 @Kanashius I have attached v1.2.8.3 of AutoItObject which fixes x64 support. The example already included in the UDF requires no changes and simply replacing this AutoItObject fixes x64. @water Provided that the original UDF zip archive gets updated with the newer version of AutoItObject for x64 support, I would strongly advocate for this UDF to be added to the UDF wiki list. It is absolutely brilliant and I am surprised that it never picked up steam initially. It has a great example script to test. As an example which I will share the code for soon when it's completed, I was able to use this UDF to very quickly and reliably create an ACL Viewer program for Windows security ACL/SDDL parsing. I have experienced zero issues with this UDF aside from the initial x64 support which is fixed with the attached file. Screenshot: AutoItObject.au3
water Posted February 26 Posted February 26 18 hours ago, WildByDesign said: I would strongly advocate for this UDF to be added to the UDF wiki list. Done WildByDesign 1 My UDFs and Tutorials: Spoiler UDFs: Active Directory (NEW 2024-07-28 - Version 1.6.3.0) - Download - General Help & Support - Example Scripts - Wiki ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts OutlookEX (2021-11-16 - Version 1.7.0.0) - Download - General Help & Support - Example Scripts - Wiki OutlookEX_GUI (2021-04-13 - Version 1.4.0.0) - Download Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki PowerPoint (2021-08-31 - Version 1.5.0.0) - Download - General Help & Support - Example Scripts - Wiki Task Scheduler (2022-07-28 - Version 1.6.0.1) - Download - General Help & Support - Wiki Standard UDFs: Excel - Example Scripts - Wiki Word - Wiki Tutorials: ADO - Wiki WebDriver - Wiki
argumentum Posted February 26 Posted February 26 (edited) .. this UDF is quite interesting but can crash quite hard. So user beware. Edited yesterday at 02:20 AM by argumentum fixed Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting.
Kanashius Posted Sunday at 06:13 PM Author Posted Sunday at 06:13 PM (edited) @WildByDesign Thanks, I'm glad you like it. I hope you will like the rework even more. With the Rework I did now, AutoItObject is not needed anymore. It only uses UDFs included with AutoIt now. The reworked UDF also makes it really easy to show Files in the TreeView as well. Just set $bShowFiles to true when adding a view. I would encourage you to switch to the new UDF, as the old one was a more early work from me. It had some bugs and was a lot less performant. @argumentum Yes, I saw that too and it also had some design mistakes and is completely redone now. It should not have these issues anymore. But feel free to tell me, if you find some anyway Edited Sunday at 06:13 PM by Kanashius WildByDesign and argumentum 2 My Website: Kanashius Webside (Some of my Programs you can find there)
WildByDesign Posted Monday at 06:51 PM Posted Monday at 06:51 PM Thank you for following up on this. I appreciate your time very much. I also am very glad that you were able to rework the UDF to not require AutoItObject anymore. I have been testing this reworked UDF quite a lot since your posted it. So far everything has been very stable, no issues. I do have something that I was wondering if you can help me with though. I don't know if it's something that you want to add to the UDF or not, but I would really like to be able to get the current path of whatever folder/file is selected while using the keyboard to navigate up and down. I should note that I am referring specifically to treeview only. I have been trying to add another Case to the Case $__TreeListExplorer__Type_TreeView section of __TreeListExplorer__WinProc function: Case $TVN_SELCHANGEDA, $TVN_SELCHANGEDW I've had some bits of success with it but mostly failures. I can get it to write a message to console each time which is great. But I am failing at getting the full path of the folder/file that is currently selected. I don't understand the new UDF fully yet.
Kanashius Posted yesterday at 12:33 AM Author Posted yesterday at 12:33 AM @WildByDesign I've added it (for both Tree- and ListView for consistency). I did it by adding a new callback for $sCallbackOnSelectionChange and renaming the old one to $sCallbackOnClick (which is what it really was... never thought about the keyboard). Yeah, the UDF is a littlebit more complex now, with all the maps and stuff To get a folder: ; Get the data for the view Local $mView = $__TreeListExplorer__Data["mViews"][$hWndFrom] ; Get Root (always ends with \), by accessing the system, the view is in, and getting its root value Local $sRoot = $__TreeListExplorer__Data.mSystems[$mView.iSystem].sRoot ; Get Folder (Folders always end with \) Local $sFolder = __TreeListExplorer__TreeViewGetRelPath($mView.iSystem, $hWndFrom, $hItem) Local $sPath = $sRoot & $sFolder I have one global map for all data (to avoid lots of global variables): $__TreeListExplorer__Data. In this map, there is different stuff saved. Among others, there is a Map with all Systems and a Map with all Views. The system data also contains a map with all views belonging to that system. The Map with all views is only for easier/faster access without having to iterate over all systems (For WinProc and when adding a view, to check, if its already in a system). So you can get the view data with the Tree-/ListView handle. In this data, there is a "iSystem" field, with the ID of the system, the view belongs to. With this ID you can then access the right system and read its values, like "sRoot" and "sFolder". The UDF is very data driven. So just changing something in the $__TreeListExplorer__Data and calling __TreeListExplorer_OpenPath($hSystem, __TreeListExplorer_GetPath($hSystem), True) may already work (if you do not touch the wrong stuff ). If you would like to get a better look, feel free to use the ToString UDF to inspect the content of $__TreeListExplorer__Data. WildByDesign 1 My Website: Kanashius Webside (Some of my Programs you can find there)
WildByDesign Posted 7 hours ago Posted 7 hours ago 17 hours ago, Kanashius said: I've added it (for both Tree- and ListView for consistency). I did it by adding a new callback for $sCallbackOnSelectionChange and renaming the old one to $sCallbackOnClick (which is what it really was... never thought about the keyboard). Thank you, I appreciate it. This worked perfectly for me. I know that keyboard input would not normally be thought of for a file explorer type of treeview, but I use it for the ACL Viewer that I am making. Any selection made will then poll the security descriptors for that file/folder and go through the parser that I ended up coding. So I also wanted the ability to navigate up and down with the keyboard as well and it works great for that purpose now that you have updated the UDF. The code snippet that you shared helped me to understand the mapping and views better now. I imagine that helped keep the UDF code smaller too which is nice. I only have one last concern. Performance, particularly for larger directories such as C:\Windows and C:\Windows\System32 for example. Most directories behave quite well. But those two examples take a good amount of time to display and will also flicker a bit once they display. How many directory levels deep to you go with each selection? Is there anything that can be done to improve the loading of those larger directories? I am referring to treeview-mode only since I don't use the listview in my current project. For comparison, there is another treeview explorer UDF called ChooseFileFolder (ChooseFileFolder - Interim Version 11 Mar 21 - AutoIt Example Scripts - AutoIt Forums). If you try it as an example, try ChooseFileFolder_Example_1.au3 and in particular play around with Ex. 3a in that file. It doesn't seem to have any delay for displaying C:\Windows. The only problem is that it lacks file/drive/folder icons and many other things that your UDF has. I don't mind having some delay when displaying larger directories. I am totally fine with that. But I am wondering if there is anything that can be done to reduce it. Especially treeview-only. I don't understand the code very well so I am not sure if it still collects the file date/time/size information for listview when listview is not used. I am still very much a beginner. Cheers!
Kanashius Posted 4 hours ago Author Posted 4 hours ago Hi @WildByDesign, thanks for providing so much feedback, thats really helpful. I was going one directory deeper, then was shown. So if you open the Windows folder, the content of all direct child directories in that folder were loaded, basically C:\Windows\* was loaded, but NOT deeper, e.g. C:\Windows\System32\*. So the depth would be current+1. I solved that now, by only looking, if there is any folder/file in that sub directory, without actually loading and adding all folders/files to the TreeView. Instead I add a dummy child, so the Expand button is shown, but the complete content of that folder is only loaded, when expanding the item. So for every child, only FileFindFirstFile is called, instead of _FileListToArray (2x, once for folders, once for files) and there is always only one child added and not all folders/files. With the latest update (v2.2.0) the opening of a folder (Tested with C:\Windows) is pretty much instant for me. WildByDesign 1 My Website: Kanashius Webside (Some of my Programs you can find there)
WildByDesign Posted 3 hours ago Posted 3 hours ago 30 minutes ago, Kanashius said: With the latest update (v2.2.0) the opening of a folder (Tested with C:\Windows) is pretty much instant for me. Thank you for the quick update. You came up with a very efficient method to handle that. The difference is literally night and day. Great work! Kanashius 1
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now