Jump to content

Recommended Posts

Posted

I have an issue in Files Au3 that might benefit from an added function to the UDF.

Whenever a user navigates to a new directory, it runs an Adlib function to get a total count of items in the ListView with _GUICtrlListView_GetItemCount. Then that total count of items (files and folders) gets updated on the statusbar. This works good most of the time.

However, some directories have more contents and are therefore slower to load and the Adlib function gets the wrong item count or no count at all.

The problem, from outside of the UDF, I don't know how to determine when the ListView is done updating the items. I wonder if something like this might be better done within the UDF.

One of the two possibilities would be good:

  • The UDF gives some indication of when the ListView is done updating, by some query function
    • This way, I know it's done and can run my function to get an accurate item count

Or

  • The UDF keeps its own ListView item count that is cleared at BeginUpdate and updated count at EndUpdate
    • This way, I can query the UDF directly for ListView item count
    • If count is 0 or Null, I know that ListView item update is still in progress (or empty directory)
    • I suppose the return would need to be unique (maybe not 0) if still in progress

Not necessary, but if you wanted to take it a step further: have a directory count, file count and total count to query with a function.

Posted

Hey there,

a new version is out. Now with support for ComboBox/ComboBoxEx.

Every view can get its own icon size now: __TreeListExplorer_SetViewIconSize

There is now a __TreeListExplorer_FileGetIconBitmap function to allow the icon to be retrieved. It is possible to get the icons for a provided path with a customizable icon size.
If there are a lot of repeating calls with the same path/extension to this function, consider adding your own cache for better performance.

Have fun with v2.13 :)

Posted (edited)
1 hour ago, Kanashius said:

Have fun with v2.13 :)

I've only just started to play around with the updated Examples, but this is super impressive! :thumbsup:

 

EDIT: 

1 hour ago, Kanashius said:

Now with support for ComboBox/ComboBoxEx.

I suppose this opens the door to the possibility of switching the path edit box into a ComboBox with the combination of using the History.au3 UDF to show previously visited directories in the combo?

Edited by WildByDesign
Posted (edited)

@Kanashius I have had success getting tooltips to load the icon obtained from the treeview and listview imagelists. However, I have spent about an hour this morning trying to get the icons directly from the updated __TreeListExplorer_FileGetIconBitmap but I have had no luck so far. I've tried about a dozen different things but I don't understand it very well.

I will share a small example that I am using to try to get it working.

#include <GUIConstantsEx.au3>
#include <GuiToolTip.au3>
#include "TreeListExplorer.au3"

Example()

Func Example()
    ; start TreeListExplorer
    __TreeListExplorer_StartUp($__TreeListExplorer_Lang_EN)

    ; attempt to get icon from Notepad
    Local $sPath = "C:\Windows\System32\notepad.exe"
    ;Local $hIcon = __TreeListExplorer_FileGetIconBitmap($sPath, 32)
    Local $hBitmap = __TreeListExplorer_FileGetIconBitmap($sPath, 32)
    Local $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap, 0x00000000)
    _GDIPlus_BitmapDispose($hBitmap)

    ;Local $hIcon = _GDIPlus_HICONCreateFromBitmap($hBitmap)

    ; Create a GUI with various controls.
    Local $g_hGUI = GUICreate("Example", 400, 400)

    $hToolTip3 = _GUIToolTip_Create(0)
    _GUIToolTip_AddTool($hToolTip3, $g_hGUI, " ", $g_hGUI)
    _GUIToolTip_UpdateTipText($hToolTip3, $g_hGUI, $g_hGUI, "Press Esc to Close")
    ;_GUIToolTip_SetTitle($hToolTip3, 'Custom Icon Example', $TTI_INFO_LARGE)
    _GUIToolTip_SetTitle($hToolTip3, 'Custom Icon Example', $hHBitmap)
    _GUIToolTip_TrackActivate($hToolTip3, True, $g_hGUI, $g_hGUI)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $g_hGUI)

    ; Loop until the user exits.
    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop

        EndSwitch

        ; track position of tooltip
        Local $aPosTool3 = MouseGetPos()
        _GUIToolTip_TrackPosition($hToolTip3, $aPosTool3[0], $aPosTool3[1])
    WEnd

    ; close TreeListExplorer
    __TreeListExplorer_Shutdown()
    _GUIToolTip_Destroy($hToolTip3)
    ; Delete the previous GUI and all controls.
    GUIDelete($g_hGUI)
EndFunc   ;==>Example

In this example, I am just trying to get the icon from Notepad. However, aside from this example the path could really be anything in the file system.

Edited by WildByDesign
Posted

I also will have a look into it @WildByDesign.
I just realized that function __TreeListExplorer_FileGetIconBitmap is only available in the newest UDF v2.13. So you also have to update "files-au3" later on, but I am sure you did this already.

I'll get back to you when I have some information. Here or via Discord, etc.

Best regards
Sven

==> AutoIt related: 🔗 Organization AutoIt Community🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet🔗 autoit-webdriver-boilerplate

Spoiler

🌍 Au3Forums

🎲 AutoIt (en) Cheat Sheet

📊 AutoIt limits/defaults

💎 Code Katas: [...] (comming soon)

🎭 Collection of GitHub users with AutoIt projects

🐞 False-Positives

🔮 Me on GitHub

💬 Opinion about new forum sub category

📑 UDF wiki list

✂ VSCode-AutoItSnippets

📑 WebDriver FAQs

👨‍🏫 WebDriver Tutorial (coming soon)

Posted (edited)

This way it worked for me:

#include-once
#include <GuiToolTip.au3>
#include "../lib/TreeListExplorer.au3" ; Adjust this and use >= v2.13 of the UDF.

Example()

Func Example()
    __TreeListExplorer_StartUp($__TreeListExplorer_Lang_EN)

    ; Notepad icon
    Local $sPath   = "C:\Windows\System32\notepad.exe"
    Local $hBitmap = __TreeListExplorer_FileGetIconBitmap($sPath, 32)
    Local $hIcon   = _GDIPlus_HICONCreateFromBitmap($hBitmap)
                     _GDIPlus_BitmapDispose($hBitmap)

    ; GUI
    Local $g_hGUI = GUICreate("Example", 400, 400)

    Local $hToolTip3 = _GUIToolTip_Create(0)
                       _GUIToolTip_AddTool($hToolTip3, $g_hGUI, " ", $g_hGUI)
                       _GUIToolTip_UpdateTipText($hToolTip3, $g_hGUI, $g_hGUI, "Press Esc to Close")
                       _GUIToolTip_SetTitle($hToolTip3, 'Custom Icon Example', $hIcon)
                       _GUIToolTip_TrackActivate($hToolTip3, True, $g_hGUI, $g_hGUI)

    GUISetState(@SW_SHOW, $g_hGUI)

    ; Event loop
    While True
        Switch GUIGetMsg()
            Case -3
                ExitLoop
        EndSwitch

        ; Track position of tooltip
        Local $aPosTool3 = MouseGetPos()
        _GUIToolTip_TrackPosition($hToolTip3, $aPosTool3[0], $aPosTool3[1])
    WEnd

    ; Dispose
    __TreeListExplorer_Shutdown()
    _GUIToolTip_Destroy($hToolTip3)
    _GDIPlus_ImageDispose($hIcon)
    GUIDelete($g_hGUI)
EndFunc

file-icon-to-tooltip.png

I cannot provide much explanation, because I am at work and have to continue.

Best regards
Sven

FYI: @WildByDesign, @Kanashius

Edited by SOLVE-SMART

==> AutoIt related: 🔗 Organization AutoIt Community🔗 GitHub, 🔗 Discord Server, 🔗 Cheat Sheet🔗 autoit-webdriver-boilerplate

Spoiler

🌍 Au3Forums

🎲 AutoIt (en) Cheat Sheet

📊 AutoIt limits/defaults

💎 Code Katas: [...] (comming soon)

🎭 Collection of GitHub users with AutoIt projects

🐞 False-Positives

🔮 Me on GitHub

💬 Opinion about new forum sub category

📑 UDF wiki list

✂ VSCode-AutoItSnippets

📑 WebDriver FAQs

👨‍🏫 WebDriver Tutorial (coming soon)

  • 2 weeks later...
Posted (edited)

@Kanashius I am thinking about adding the TreeListExplorer version to the About dialog in Files Au3 so that we know what is under-the-hood in any given release and to give some extra credit to your UDF. But I am not sure what the best way for parsing the string is.

; Version .......: 2.13

I am not the best when it comes to manipulating strings. I suppose it would involve reading the UDF file and grabbing what comes after ; Version .......:

I just want to ensure that whatever method is used to get the version is as future-proof as possible.

EDIT: Now that I think about it, this may not work in a situation where it’s compiled to binary.

Edited by WildByDesign
Posted (edited)
2 hours ago, WildByDesign said:

I just want to ensure that whatever method is used to get the version is as future-proof as possible.

I'am using the default for comments/librarys/... for AutoIt. So I wrote this script, which should work for up to 4 version numbers and a possible a/b/rc at the end for the alpha, beta and release candidate versions.

#include <File.au3>
ConsoleWrite(_VersionPrint(_UDFGetVersion("AutoItIPC\IPC.au3"))&@crlf)
ConsoleWrite(_VersionPrint(_UDFGetVersion("AutoItTreeListExplorer\TreeListExplorer.au3"))&@crlf)

Local $sAutoItIncludeFolder = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "\", 0, -1)-1)&"\"&"Include"
Local $arFiles = _FileListToArray($sAutoItIncludeFolder)
For $i = 1 to UBound($arFiles)-1 Step 1
    ConsoleWrite(_VersionPrint(_UDFGetVersion($sAutoItIncludeFolder&"\"&$arFiles[$i]))&" >> "&$arFiles[$i]&@crlf)
Next

Func _VersionToString($arVersion, $sSep = " ")
    If Not IsArray($arVersion) Or UBound($arVersion, 0)<2 Or UBound($arVersion, 1)<2 Then Return SetError(1, 1, "Version not parsed.")
    Local $sVersion = ""
    If $arVersion[0][0]>0 Then
        $sVersion &= "AutoIt Version: "
        $sVersion&=$arVersion[0][1]&" ["
        For $i=1 to $arVersion[0][0]-1
            If $i>1 Then $sVersion &= ", "
            $sVersion &= $arVersion[0][1+$i]
        Next
        If $arVersion[0][0]>0 Then $sVersion&="]"
        If $arVersion[1][0]>0 Then $sVersion &= $sSep
    EndIf
    If $arVersion[1][0]>0 Then
        $sVersion &= "UDF Version: "
        $sVersion&=$arVersion[1][1]&" ("
        For $i=1 to $arVersion[1][0]-1
            If $i>1 Then $sVersion &= ", "
            $sVersion &= $arVersion[1][1+$i]
        Next
        If $arVersion[1][0]>0 Then $sVersion&="]"
    EndIf
    If $sVersion = "" Then Return "Version unknown"
    Return $sVersion
EndFunc

Func _UDFGetVersion($sFile)
    Local $sCode = FileRead($sFile)
    If @error Then Return SetError(@error, @extended, 0)
    Local $arVersion = _GetVersion($sCode)
    If @error Then Return SetError(@error, @extended, -1)
    Return $arVersion
EndFunc

; #FUNCTION# ====================================================================================================================
; Name ..........: _GetVersion
; Description ...: Get the AutoIt Version as well as the UDF Version.
; Syntax ........: _GetVersion($sUdfCode)
; Parameters ....: $sUdfCode               - the sourcecode of the udf
; Return values .: Array with version information.
; Author ........: Kanashius
; Modified ......:
; Remarks .......: @extended (1 - Only AutoIt Version found, 2 - Only UDF Version found, 3 - Both found)
;                  Resurns a 2D-Array with:
;                  [0][0] being the amount of version parts found for the AutoIt Version + 1
;                  [0][1] If [0][0]>0 then this is the full autoit version as string
;                  [0][2] The first part of the autoit version (index 2-5 is a number)
;                  ...
;                  [0][6] The last part of the autoit version (last part is a/b/rc)
;                  [1][0] being the amount of version parts found for the UDF Version + 1
;                  [1][1] If [1][0]>0 then this is the full udf version as string
;                  [1][2] The first part of the udf version (index 2-5 is a number)
;                  ...
;                  [1][6] The last part of the udf version (last part is a/b/rc)
; Related .......:
; Link ..........:
; Example .......: No
; ===============================================================================================================================
Func _GetVersion($sUdfCode)
    Local $iExtended = 0
    Local $arAutoItVersion = StringRegExp($sUdfCode, "(?m)(?s)^;\s*#INDEX#\s*=*.*?;\s*AutoIt\s*Version\s*\.*:\s((\d+)(?:\.(\d+)(?:\.(\d+)(?:\.(\d+))?)?)?(a|b|rc)?)\s*$", 1)
    If Not @error Then $iExtended = 1
    Local $arUDFVersion =  StringRegExp($sUdfCode, "(?m)(?s)^;\s*#INDEX#\s*=*.*?;\s*Version\s*\.*:\s((\d+)(?:\.(\d+)(?:\.(\d+))?)?(a|b|rc)?)\s*$", 1)
    If Not @error Then $iExtended += 2
    Local $iVerNumbers = UBound($arAutoItVersion)
    If UBound($arUDFVersion)>$iVerNumbers Then $iVerNumbers = UBound($arUDFVersion)
    Local $arResult[2][$iVerNumbers+1]
    $arResult[0][0] = UBound($arAutoItVersion)
    For $i=0 to UBound($arAutoItVersion)-1 Step 1
        $arResult[0][$i+1] = $arAutoItVersion[$i]
    Next
    $arResult[1][0] = UBound($arUDFVersion)
    For $i=0 to UBound($arUDFVersion)-1 Step 1
        $arResult[1][$i+1] = $arUDFVersion[$i]
    Next
    Return SetExtended($iExtended, $arResult)
EndFunc

This can detect AutoIt Version and Version and the following version numbers:

1
1.1
1.1.1
1.1.1.1
1.1.1.1a
1.1.1.1b
1.1.1.1rc

with 1 being detected by \d+ => one or more numbers.

Hope this helps you :)

Edited by Kanashius
Posted
On 2/9/2026 at 11:19 AM, Kanashius said:

Hope this helps you :)

This script helps a lot. It works very well and I can see others benefiting from it too.

I do have one problem though. When the script (in this case Files Au3) is compiled to binary, it can no longer obtain the UDF version to show in the About dialog. And I'm not sure how else to generate it other than manually each release.

Do you know of any other way?

For example, during compilation of the binary, maybe it can call that function and store the result in a variable or string. But I just don't know how I could achieve that. I could have it write it to a text file or something but that would be not good. There is probably something easy that I am missing and just can't think of it right now.

Posted (edited)

Feature Request:

I was thinking about this the other day. By default, TreeListExplorer UDF shows all of the files and folders that are not normally shown in File Explorer that I believe are related to the "Hide protected operating system files" option. For example, showing the $RECYCLE.BIN folders on each drive, the Documents and Settings folder, System Volume Information, etc.

"Hide protected operating system files" seems to be quite a bit different from the "Show hidden files, folders, and drives" option.

I am not entirely sure what attributes are set to determine "Hide protected operating system files" or how File Explorer handles that internally.

If it is possible to add such an option for TreeListExplorer UDF, in a way where you could enable/disable either of those settings, I think that would be an excellent feature to have.

EDIT: Looks like we would just have to look for the "S" = SYSTEM attribute.

Edited by WildByDesign
Posted (edited)
8 hours ago, WildByDesign said:

If it is possible to add such an option for TreeListExplorer UDF, in a way where you could enable/disable either of those settings, I think that would be an excellent feature to have.

I thought about that and then I remembered, that the filter callback exists, so I thought it is not really needed:

__TreeListExplorer_SetCallback($hView, $__TreeListExplorer_Callback_Filter, "_filterListView")

Func _filterListView($hSystem, $hView, $bIsFolder, $sPath, $sName, $sExt)
    Return Not StringInStr(FileGetAttrib($sPath&$sName&$sExt), "S")
EndFunc

(Check if $sPath&$sName&$sExt is the correct absolute path, I am not entirely sure and cannot test at the moment.)

The Filter callback is checked AFTER $__TreeListExplorer_Callback_ListViewPaths. It is a little bit redundant with the new $__TreeListExplorer_Callback_ListViewPaths callback (because that can be used to remove entries as well), but I thought to leave it there, because it may be easier to use, if simple filtering without sorting is sufficient.

8 hours ago, WildByDesign said:

Do you know of any other way?

I published the functions as UDF: 

You can use the UDF to store the version in global const variables. The first time, they will be positioned at the top, but you can move them and if you run the script again, it will update them at their current location. So you need to run your script once, after changing a UDF file to a different version.
It was the closest, I could think of and I hope this helps you :)

Edited by Kanashius
Posted
2 hours ago, Kanashius said:

(Check if $sPath&$sName&$sExt is the correct absolute path, I am not entirely sure and cannot test at the moment.)

Yes, this does give the correct full path.

2 hours ago, Kanashius said:

The Filter callback is checked AFTER $__TreeListExplorer_Callback_ListViewPaths. It is a little bit redundant with the new $__TreeListExplorer_Callback_ListViewPaths callback (because that can be used to remove entries as well), but I thought to leave it there, because it may be easier to use, if simple filtering without sorting is sufficient.

The example function _filterListView that you shared works well. I created a similar callback function for the TreeView and it worked good. Thank you.

2 hours ago, Kanashius said:

You can use the UDF to store the version in global const variables. The first time, they will be positioned at the top, but you can move them and if you run the script again, it will update them at their current location. So you need to run your script once, after changing a UDF file to a different version.
It was the closest, I could think of and I hope this helps you :)

This is fantastic. I haven't got a chance to test the new UDF yet but I will test it tonight.

Posted

It seems that using the Filter Callback to filter out files/folders with the system attribute causes some random issues.

Screenshot in spoiler:

Spoiler

system.png

It is especially reproducible in the System32 directory. It displays duplicates of those 4-digit language related folders. And, as seen in screenshot, sometimes display them as files instead of folders. And being random, it will show differently each time you open the System32 directory. System32 is the easiest place to repro it but it likely happens in other areas too.

Posted
3 hours ago, WildByDesign said:

It seems that using the Filter Callback to filter out files/folders with the system attribute causes some random issues.

I looked into that and could not find a problem with the filter callback (see example file).
The callback is also just one additional If, preventing the listview-entry from being added, so I think the problem you have cannot even come from that.

I assume you are using the $__TreeListExplorer_Callback_ListViewPaths callback (for sorting,...). There you are really editing/changing the array, with which the data is added. I think the probability is high, that something is going wrong there (before the filter callback is even called).

TreeListExplorer-Example-HiddenSystemFiles.au3

Posted
7 minutes ago, Kanashius said:

I looked into that and could not find a problem with the filter callback (see example file).
The callback is also just one additional If, preventing the listview-entry from being added, so I think the problem you have cannot even come from that.

You are right. I just confirmed by disabling the Callback_Filter that I was testing. The issue still persisted.

7 minutes ago, Kanashius said:

I assume you are using the $__TreeListExplorer_Callback_ListViewPaths callback (for sorting,...). There you are really editing/changing the array, with which the data is added. I think the probability is high, that something is going wrong there (before the filter callback is even called).

I had already done my testing with both Callback_ListViewPaths and Callback_ListViewItemCreated disabled. The AddView is also set to the default options so that there is no additional processing going on.

To my surprise, the issue still persists. With all default settings, that random issue (at least noticeable in System32) is still happening. I will have to dig into this some more.

Posted (edited)

So far I have not been able to reproduce the phantom file/folder on TLE 2.12 at all. On 2.13, it seems to happen (randomly) even when I don’t have any callbacks or custom columns. All default views and so on.

Sometimes it does not do it at all. Sometimes it does it many times. So completely random and I don’t even understand how folders are turning into files and showing duplicate entries and more.

I will keep doing more testing to figure out what is causing it and let you know if I can make sense of it.

EDIT: I figured out the issue. It seems to be only a visual glitch that only shows if I have the cursor hovering over the ListView while it is still populating a large directory such as System32. It does not show with your examples since they don't have the theme styles applied to them.

I already have the Callback_Loading function for certain purposes. So I think what I can do to fix this (in Files Au3) is by disabling input to the ListView from the time that loading has started until loading is complete and then enable the input again.

EDIT2: It ended up being an easy fix and worked perfectly. In the Callback_Loading function, I just had to do the following:

If $bLoading Then
        _WinAPI_EnableWindow($g_hListview, False)
    Else
        _WinAPI_EnableWindow($g_hListview, True)
    EndIf

What a weird problem. Thankfully it was only a visual glitch and with an easy fix.

Edited by WildByDesign

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
×
×
  • Create New...