jcpetu Posted November 24, 2020 Share Posted November 24, 2020 (edited) Hi people, I'm developing a file browser and I found an erratic behavior of TreeView, it some times brings data OK and sometimes repeats all directory structure. I don't get to see what I'm doing wrong. I'll appreciate any help. expandcollapse popup#include <File.au3> #include <GUIConstantsEx.au3> #include <GUITreeView.au3> #include <GuiListView.au3> #include <WindowsConstants.au3> ;---------------------------------------------------------------------------------------------------------------------- Opt("GUIOnEventMode", 1) #Region Variables ----------------------------------------------------------------------------------------------------- Global $times Global $GuiFileExplorer, $TVFileExplorer, $BChangeProperties, $LVBrowseItems, $drives Global $DeskW = 700, $DeskH = 700, $TVLVHeigth = 550 Global $TVImage = _GUIImageList_Create(16, 16, 5, 2) _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 3) ;--Folder _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 4) ;--Folder Open _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 181) ;-Cdr _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 8) ;--Fixed _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 7) ;--Removable _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 9) ;--Network _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 11) ;-CDRom _GUIImageList_AddIcon($TVImage, @SystemDir & "\shell32.dll", 109) ;No Symbol for Burner #EndRegion Variables ----------------------------------------------------------------------------------------------------- $GuiFileExplorer = GUICreate('File Browser OM - v1.0', $DeskW, $DeskH, -1, -1, $WS_SIZEBOX + $WS_SYSMENU + BitOR($WS_MAXIMIZEBOX, $WS_MINIMIZEBOX)) GUISetOnEvent($GUI_EVENT_CLOSE, "CloseGUI") $TVFileExplorer = GUICtrlCreateTreeView(16, 40, ($DeskW / 2) - 26, $TVLVHeigth, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS, $WS_GROUP, $WS_TABSTOP, $WS_BORDER)) GUICtrlSetResizing(-1, 1) _GUICtrlTreeView_SetNormalImageList(-1, $TVImage) $LVBrowseItems = GUICtrlCreateListView('', ($DeskW / 2) + 10, 40, ($DeskW / 2) - 25, $TVLVHeigth, -1, BitOR($LVS_EX_CHECKBOXES, $LVS_EX_SUBITEMIMAGES, $LVS_EX_CHECKBOXES, $LVS_EX_FULLROWSELECT, $LVS_EX_HEADERDRAGDROP, $LVS_EX_DOUBLEBUFFER)) _GUICtrlListView_AddColumn(-1, 'Name', 110, 0) ;2=left aligned _GUICtrlListView_AddColumn(-1, 'Type', 110, 0) _GUICtrlListView_AddColumn(-1, 'Size', 110, 0) ColumnResize($GuiFileExplorer) $BChangeProperties = GUICtrlCreateButton('Change', 10, 630, 81, 21) GUICtrlSetResizing(-1, 1) GUICtrlSetOnEvent(-1, 'ChangeProperties') $drives = DriveGetDrive('ALL') If Not @error Then For $x = 1 To $drives[0] $icon = 0 If DriveGetType($drives[$x]) = 'Fixed' Then $icon = 3 If DriveGetType($drives[$x]) = 'Removable' Then $icon = 4 If DriveGetType($drives[$x]) = 'Network' Then $icon = 5 If DriveGetType($drives[$x]) = 'CDROM' Then $icon = 6 If DriveGetType($drives[$x]) = 'REMOVABLE' Then $icon = 6 If $icon = 0 Then $new = _GUICtrlTreeView_AddChild($TVFileExplorer, '', $drives[$x], 0, 1) Else $new = _GUICtrlTreeView_AddChild($TVFileExplorer, '', $drives[$x], $icon, $icon) EndIf Next EndIf GUISetState(@SW_SHOW, $GuiFileExplorer) GUIRegisterMsg($WM_NOTIFY, 'WM_NOTIFY') PopulateTreeViewi($TVFileExplorer, $drives[1]) ;First drive=ROOT While Sleep(5) WEnd Func CloseGUI() GUIDelete() Exit EndFunc ;==>CloseGUI Func ChangeProperties() ConsoleWrite('Button pressed ' & @CR) EndFunc ;==>ChangeProperties Func ColumnResize(ByRef $hWnd, $type = 0) $winpos = WinGetPos($GuiFileExplorer) _GUICtrlListView_SetColumnWidth($hWnd, 0, $winpos[2] * .2375) _GUICtrlListView_SetColumnWidth($hWnd, 1, $winpos[2] * .1575) _GUICtrlListView_SetColumnWidth($hWnd, 2, $winpos[2] * .1) EndFunc ;==>ColumnResize Func PopulateTreeViewi($hWnd, $drive) ;Initial TreeView population $item = _GUICtrlTreeView_GetSelection($hWnd) ;Get the first item to populate folders If _GUICtrlTreeView_GetChildCount($hWnd, $item) <= 0 Then ;To ensure it wasn't populated _GUICtrlTreeView_BeginUpdate($hWnd) ;----------------------------------------------| $aFolders = _FileListToArray($drive, '*', 2) ;Search folders only For $i = 1 To UBound($aFolders) - 1 _GUICtrlTreeView_AddChild($hWnd, $item, $aFolders[$i], 0, 1) Next _GUICtrlTreeView_EndUpdate($hWnd) ;-------------------------------------------------| EndIf EndFunc ;==>PopulateTreeViewi Func PopulateTreeView($hWnd) $item = _GUICtrlTreeView_GetSelection($TVFileExplorer) If _GUICtrlTreeView_GetChildCount($TVFileExplorer, $item) <= 0 Then ;avoid load twice _GUICtrlTreeView_BeginUpdate($TVFileExplorer) ;----------------------------------------------| $txt = _GUICtrlTreeView_GetText($TVFileExplorer, $item) Do $parent = _GUICtrlTreeView_GetParentHandle($TVFileExplorer, $item) If $parent <> 0 Then $txt = _GUICtrlTreeView_GetText($TVFileExplorer, $parent) & "\" & $txt ;ConsoleWrite($txt&@CRLF) ; <----------- $item = $parent EndIf Until $parent = 0 ConsoleWrite('-----------------------'&@CRLF) ConsoleWrite($parent&@CRLF) ConsoleWrite($txt&@CRLF) ; <----------- ConsoleWrite($item&@CRLF) $item = _GUICtrlTreeView_GetSelection($TVFileExplorer) $aFolders = _FileListToArray($txt, "*", 2) If IsArray($aFolders) Then For $i = 1 To UBound($aFolders) - 1 _GUICtrlTreeView_AddChild($TVFileExplorer, $item, $aFolders[$i], 0, 1) Next EndIf _GUICtrlTreeView_EndUpdate($TVFileExplorer) ;-------------------------------------------------| EndIf EndFunc ;==>PopulateTreeView Func PopulateListView($hWnd) EndFunc Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR $HTVFileExplorer = ControlGetHandle($hWnd, '', $TVFileExplorer) ;TreeView handeler $HLVBrowseItems = ControlGetHandle($hWnd, '', $LVBrowseItems) ;ListView handeler $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") If $iCode = -12 Or $iCode = -17 Then Return False Switch $hWndFrom Case $HLVBrowseItems ;ListView Switch $iCode Case $NM_DBLCLK ;double click on ListView #cs If $item[0] <> 0 Then $filefolder = _GUICtrlListView_GetSelectedIndices($LVBrowseItems, True) If _GUICtrlListView_GetItemText($LVBrowseItems, $filefolder[1], 1) = "Folder" Then $idx = _GUICtrlTreeView_GetSelection($TVFileExplorer) $item = StringTrimLeft($item[1], StringInStr($item[1], "\", 0, -1)) $found = _GUICtrlTreeView_FindItem($TVFileExplorer, $item, False, $idx) _GUICtrlTreeView_SelectItem($TVFileExplorer, $found) PopulateTreeView($TVFileExplorer) PopulateListView($TVFileExplorer) Else Run(@ComSpec & " /c " & Chr(34) & $item[1] & Chr(34), "", @SW_HIDE) Sleep(800) EndIf EndIf #ce Return True EndSwitch Case $HTVFileExplorer ;TreeView Switch $iCode Case -451 PopulateTreeView($TVFileExplorer) ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<------------ ;PopulateListView($TVFileExplorer) Return True EndSwitch EndSwitch EndFunc ;==>WM_NOTIFY The first printout shows the erratic behavior and the second is after I stop the script and run it again without changing anything. Edited November 24, 2020 by jcpetu Add info. Link to comment Share on other sites More sharing options...
Nine Posted November 24, 2020 Share Posted November 24, 2020 Unable to replicate your issue... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
jcpetu Posted November 24, 2020 Author Share Posted November 24, 2020 Hi Nine, thanks for trying anyway. Yes, it's strange, it happens randomly and I don't have any idea why. I got last Autoit & SciTe versions and Win 8.11, but I don't get any connection with this behavior. Link to comment Share on other sites More sharing options...
water Posted November 24, 2020 Share Posted November 24, 2020 Works fine on Windows 10 and AutoIt 3.3.14.5. 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 Link to comment Share on other sites More sharing options...
jcpetu Posted November 24, 2020 Author Share Posted November 24, 2020 Thanks water. Link to comment Share on other sites More sharing options...
LarsJ Posted November 24, 2020 Share Posted November 24, 2020 The techniques that you demonstrate in the code in the first post only work for folders and files that are actually stored on disk. Many of the folders and files especially near the top of the C drive are virtual folders and files that are not stored on disk. These virtual folders and files are identified through PIDLs. You can find information about the concepts in Common Explorer Concepts. The information in the link appears to be about Windows XP. However, in modern file systems like in Windows 10, PIDLs are not used to traverse a file system. Here you use COM interfaces. In AutoIt, COM interfaces are implemented through the ObjCreateInterface() function. There are two essential interfaces for traversing a file system. One is INameSpaceTreeControl used to implement the treeview on the left side of File/Windows Explorer. The other is IExplorerBrowser used to implement the listview on the right side of File/Windows Explorer. Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
jcpetu Posted November 25, 2020 Author Share Posted November 25, 2020 (edited) Hi LarsJ, very interesting info, unfortunately I don't know how to implement it in Autoit. Would you mind to provide me an example for a File/Windows Explorer please? My idea was to create an explorer to been able to find & select a file, and view or change file properties. Edited November 25, 2020 by jcpetu Add info. Link to comment Share on other sites More sharing options...
LarsJ Posted November 25, 2020 Share Posted November 25, 2020 (edited) You can find a File/Windows Explorer implementation based on IExplorerBrowser in this post. It's the Toolbar example in the 7z-file. The code is from March 2015 and is Windows 7 code. I think the code can run as it is on Windows 10. You can see several of these virtual folders in the treeview on the left side of the image. The 7z-file below contains treeview code based on INameSpaceTreeControl. The code is from the last day of July 2016 and is probably made on a rainy day during the summer holidays. It's an absolute minimum implementation. I think the code can run as it is on Windows 10. This is an image of the GUI: In addition to problems accessing some of the folders, the huge disks used now can become a problem. These disks can contain a very large number of folders and files. Sooner or later you'll run into performance issues when in pure AutoIt code you have to fill in a treeview and a listview with all these folders and files. Again, the solution is to use code implemented in Microsoft DLL-files such as these COM interfaces. If you can limit the number of folders and files e.g. on the basis of a search or the like, it's certainly possible to implement a GUI in pure AutoIt code. But you can still easily run into a number of problems. Getting the right icons is not always easy. Implementing a proper right-click menu to set file properties is not entirely trivial. Especially not if you have multiple selections enabled in the listview. Again, the solution is to implement the functionality through Microsoft code in a DLL-file. LeftPane.7z Edited November 25, 2020 by LarsJ jcpetu 1 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted November 25, 2020 Moderators Share Posted November 25, 2020 jcpetu, If you want to see how I went about producing an Explorer-like TreeView then take a look at my ChooseFileFolder UDF (the link is in my sig). As LarsJ points out, pure AutoIt code is pretty slow and so the UDF only expands branches when needed to reduce the overhead. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
jcpetu Posted November 25, 2020 Author Share Posted November 25, 2020 LarsJ, thanks for the code I'll study it. Melba23, thanks a lot I'll also study it and see what I can pick of both examples. And yes, I noticed TreView & ListView population are to slow with large folders, as windows for instance, and it hangs the program because WM_NOTIFY fires both populations and can't wait for so long. Thanks again. Link to comment Share on other sites More sharing options...
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