Jump to content

TreeView erratic behavior?


jcpetu
 Share

Recommended Posts

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.

#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

 

Error1.JPG

OK1.JPG

The first printout shows the erratic behavior and the second is after I stop the script and run it again without changing anything.

Edited by jcpetu
Add info.
Link to comment
Share on other sites

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

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.

Link to comment
Share on other sites

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 by jcpetu
Add info.
Link to comment
Share on other sites

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:

1TIyUL6.png

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 by LarsJ
Link to comment
Share on other sites

  • Moderators

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

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png 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 columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

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

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...