Jump to content

Recommended Posts

Posted
22 hours ago, ioa747 said:

I haven't understood what exactly it does

Hey, thanks for the hint, I removed the additional assignation. This is just a State-Variable used internally (The __TreeListExplorer__IsViewUpdating and __TreeListExplorer__SetViewUpdating function are marked as "INTERNAL_USE_ONLY").
As an example: It is used to suppress treeview-item expansion events in the __TreeListExplorer__WinProc function from propagating when items are expanded internally by the UDF. This could cause looping effects or multiple loadings of items,... otherwise.

I fixed it locally, but as it is just a different number and has no code behaviour differences, it will just be pushed with the next update.

 

 

19 hours ago, WildByDesign said:

For what it's worth, I haven't noticed any consequences or issues with that uncommented line.

If you change line 231in your code to __TreeListExplorer_AddView($hTLESystem, $idTreeView, Default, True, "_clickCallback")
and then navigate to a folder in the TreeView and select some files there, you will see, that they will stay selected in the ListView.

The same will happen if you use __TreeListExplorer_OpenPath with a $sSelect somewhere in your application, e.g.:

__TreeListExplorer_OpenPath($hSystem, @DesktopDir, "tmp1.txt")
__TreeListExplorer_OpenPath($hSystem, @DesktopDir, "tmp2.txt")

The it will start selecting multiple files in the ListView instead of just the one from the last call.
(And maybe some other edge cases I did not think about...).
So, maybe you do not see it yet, but if something pops up during further development, it could be because of this, so be careful with that :)

 

I'am looking into the multiselect thing currently :)

Posted (edited)

Hey, @WildByDesign, I got around to adding the requested features.

- The UDF now allows for selection with ctrl/shift+left-click and to select everything with ctrl+a. If any shortcuts are missing and should be added, feel free to hit me up :)
- The 
__TreeListExplorer_AddView function has an additional parameter to allow for the removal of the ".." folder without disabling the navigation.
- It is now possible to use custom columns. Only the first column has to stay as the file/folder/drive-name. So feel free to add your own columns after that. To allow for setting these columns, another callback function was added to __TreeListExplorer_AddView: $sCallbackLVItem. This can be used to set the text for any sub items (I added this in the example so its easier to understand). When the callback function is provided, the default columns no longer replace existing other columns (only the first is added if missing).

Have fun with the new version :)

PS: __TreeListExplorer__GetSizeString is marked for internal use, but feel free to use it to calculate the string for byte sizes (e.g. Bytes/KB/MB/GB/TB/...) with e.g. __TreeListExplorer__GetSizeString(8912403)

Edited by Kanashius
Posted
11 minutes ago, Kanashius said:

Have fun with the new version :)

Apparently Christmas is TODAY! 😁

All of those new features... I am speechless. I will mess around with it right away and test it out. I will respond more later because I am still in shock at these new features.

Posted

I just noticed that the time (Date Created and Date Modified) returned from __TreeListExplorer__GetTimeString, and therefore likely from FileGetTime, is all exactly 1 hour before the times that show in File Explorer. This isn't specific to the latest 2.11.1 as it seems to be like that in previous releases as well. A quick test right now shows that FileGetTime is the culprit.

I assume this has something to do with changes in daylight savings time.

But I wonder, how does File Explorer obtain it's times for date created and modified?

Posted
3 hours ago, Kanashius said:

The UDF now allows for selection with ctrl/shift+left-click and to select everything with ctrl+a. If any shortcuts are missing and should be added, feel free to hit me up

Those all seem to be working great. The only issue that I'm having is when I use the mouse to drag and select a bunch of files and folders, it highlights the selected items and then clears all of them except for one. You can try the 2025-12-14 release of Files Au3 that I just uploaded to see what I mean. It has your latest 2.11.1 UDF release implemented.

This is fixed when I comment the following line (same as mentioned before):

;_GUICtrlListView_SetItemSelected($hView, $arSel[$j], False)

Although, as you mentioned, it would have consequences.

Do you know how we can allow multi-select by mouse click and drag without this issue?

Thank you :)

Posted

@Kanashius I was curious to try a sort possibility in your example (the listview from the left side) by using GUICtrlListView_RegisterSortCallBack() . It worked fine and required only 4 additional lines in the example to make it functional, we'll see the code later. But first I'd like to ask about this line found in TreeListExplorer.au3

GUICtrlSetStyle($hView, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT))

The fact that you added the $LVS_NOSORTHEADER style seems to show that you prefer to avoid the sort in the UDF. But if not mistaken, this line will not add $LVS_NOSORTHEADER to the listview styles, let's try to show this behavior with an example, based on example #1 of topic GUICtrlListView_RegisterSortCallBack() found in AutoIt help file, this is what should happen :

#include <GUIConstantsEx.au3>
#include <GuiImageList.au3>
#include <GuiListView.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

Opt("MustDeclareVars", 1)

Example()

Func Example()
    Local $aIcons[3] = [0, 3, 6]
    Local $iExWindowStyle = BitOR($WS_EX_DLGMODALFRAME, $WS_EX_CLIENTEDGE)
    Local $iExListViewStyle = BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_SUBITEMIMAGES, $LVS_EX_GRIDLINES, $LVS_EX_CHECKBOXES, $LVS_EX_DOUBLEBUFFER)

    GUICreate("ListView Sort (v" & @AutoItVersion & ")", 300, 200)

;~  ; ==================
;~  ; 1) One proper way to add the $LVS_NOSORTHEADER style to a listview (headers no more clickable +++)
;~      Local $idListView = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180, _
;~      BitOR($GUI_SS_DEFAULT_LISTVIEW, $LVS_NOSORTHEADER), $iExWindowStyle)
;~  ;
;~  ; ListView styles : LVS_REPORT, LVS_SINGLESEL, LVS_SHOWSELALWAYS, LVS_NOSORTHEADER, WS_CHILD, WS_VISIBLE, WS_GROUP, WS_TABSTOP
;~  ; Header syles    : HDS_DRAGDROP, HDS_FULLDRAG, WS_CHILD, WS_VISIBLE
;~  ; ==================

;~  ; ==================
;~  ; 2) Another way to add the $LVS_NOSORTHEADER style to a listview... but headers still clickable
;~  Local $idListView = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180, -1, $iExWindowStyle)
;~  Local $hListView = GUICtrlGetHandle($idListView)
;~  Local $i_Style_Old = _WinAPI_GetWindowLong($hListView, $GWL_STYLE)
;~  _WinAPI_SetWindowLong($hListView, $GWL_STYLE, BitOR($i_Style_Old, $LVS_NOSORTHEADER))
;~  ;
;~  ; ListView styles : LVS_REPORT, LVS_SINGLESEL, LVS_SHOWSELALWAYS, LVS_NOSORTHEADER, WS_CHILD, WS_VISIBLE, WS_GROUP, WS_TABSTOP
;~  ; Header syles    : HDS_BUTTONS, HDS_DRAGDROP, HDS_FULLDRAG, WS_CHILD, WS_VISIBLE
;~  ; ==================

    ; ==================
    ; 3) Wrong way to add the $LVS_NOSORTHEADER style to a listview (it won't add it... and headers still clickable)
    Local $idListView = GUICtrlCreateListView("Column1|Col2|Col3", 10, 10, 280, 180, -1, $iExWindowStyle)
    Local $hListView = GUICtrlGetHandle($idListView)
    Local $i_Style_Old = _WinAPI_GetWindowLong($hListView, $GWL_STYLE)
    GUICtrlSetStyle($hListView, BitOR($i_Style_Old, $LVS_NOSORTHEADER)) ; this won't add $LVS_NOSORTHEADER
    ;
    ; ListView styles : LVS_REPORT, LVS_SINGLESEL, LVS_SHOWSELALWAYS, WS_CHILD, WS_VISIBLE, WS_GROUP, WS_TABSTOP
    ; Header syles    : HDS_BUTTONS, HDS_DRAGDROP, HDS_FULLDRAG, WS_CHILD, WS_VISIBLE
    ; ==================

    _GUICtrlListView_SetExtendedListViewStyle($idListView, $iExListViewStyle)

    ; Set ANSI format
;~     _GUICtrlListView_SetUnicodeFormat($idListView, False)

    ; Load images
    Local $hImage = _GUIImageList_Create(18, 18, 5, 3)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -7)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -12)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -3)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -4)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -5)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -6)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -9)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -10)
    _GUIImageList_AddIcon($hImage, @SystemDir & "\shell32.dll", -11)
    _GUICtrlListView_SetImageList($idListView, $hImage, 1)

    _AddRow($idListView, "ABC|000666|10.05.2004", $aIcons)
    _AddRow($idListView, "DEF|444|11.05.2005", $aIcons, 1)
    _AddRow($idListView, "CDE|555|12.05.2004", $aIcons, 2)

    GUISetState(@SW_SHOW)

    _GUICtrlListView_RegisterSortCallBack($idListView)

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                ExitLoop
            Case $idListView
                ; Kick off the sort callback
                _GUICtrlListView_SortItems($idListView, GUICtrlGetState($idListView))
        EndSwitch
    WEnd

    _GUICtrlListView_UnRegisterSortCallBack($idListView)
    GUIDelete()
EndFunc   ;==>Example

Func _AddRow($hWnd, $sItem, $aIcons, $iPlus = 0)
    Local $aItem = StringSplit($sItem, "|")
    Local $iIndex = _GUICtrlListView_AddItem($hWnd, $aItem[1], $aIcons[0] + $iPlus, _GUICtrlListView_GetItemCount($hWnd) + 9999)
    _GUICtrlListView_SetColumnWidth($hWnd, 0, $LVSCW_AUTOSIZE_USEHEADER)

    For $x = 2 To $aItem[0]
        _GUICtrlListView_AddSubItem($hWnd, $iIndex, $aItem[$x], $x - 1, $aIcons[$x - 1] + $iPlus)
        _GUICtrlListView_SetColumnWidth($hWnd, $x - 1, $LVSCW_AUTOSIZE)
    Next
EndFunc   ;==>_AddRow

You'll notice 3 ways to add the LVS_NOSORTHEADER style, please try them all (commenting out 2 ways each time)
As you can see, the 3rd way (which uses GUICtrlSetStyle as in your UDF) doesn't add the style to the LV and doesn't automatically remove the $HDS_BUTTONS from the header, which means the header buttons are still clickable, when you probably didn't want them to be. For the record, a way to have the headers non-clickable could be to add 3 extra lines :

Local $hHeader = _GUICtrlListView_GetHeader($idListView)
Local $i_Style_Old = _WinAPI_GetWindowLong($hHeader, $GWL_STYLE)
_WinAPI_SetWindowLong($hHeader, $GWL_STYLE, BitXOR($i_Style_Old, $HDS_BUTTONS))

So, if not mistaken, in your UDF, the line GUICtrlSetStyle doesn't add the LVS_NOSORTHEADER to the LV and the final LV styles are the same, with or without the GUICtrlSetStyle line (tested) :

TreeListExplorer.au3

With line GUICtrlSetStyle($hView, BitOR($LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER, $LVS_REPORT))
LV styles     : LVS_REPORT, LVS_SINGLESEL, LVS_SHOWSELALWAYS, WS_CHILD, WS_VISIBLE, WS_TABSTOP
Header styles : HDS_BUTTONS, HDS_DRAGDROP, HDS_FULLDRAG, WS_CHILD, WS_VISIBLE

Without the GUICtrlSetStyle line (same styles in LV & header !)
LV styles     : LVS_REPORT, LVS_SINGLESEL, LVS_SHOWSELALWAYS, WS_CHILD, WS_VISIBLE, WS_TABSTOP
Header styles : HDS_BUTTONS, HDS_DRAGDROP, HDS_FULLDRAG, WS_CHILD, WS_VISIBLE

Now back to your example. The following main loop should sort the leftside LV and show the corresponding arrow sort :

_GUICtrlListView_RegisterSortCallBack($idListViewLeft, 2) ; 2 = natural sort

while True
    Switch GUIGetMsg()
        Case -3 ; $GUI_EVENT_CLOSE
            _GUICtrlListView_UnRegisterSortCallBack($idListViewLeft)
            __TreeListExplorer_Shutdown()
            Exit
        Case $idButtonTest
            __TreeListExplorer_Reload($hTLESystemRight, True) ; reload all folders in the right system
            __TreeListExplorer_Reload($hTLESystemLeft, True) ; reload folder in the right system
        Case $idListViewLeft
            _GUICtrlListView_SortItems($idListViewLeft, GUICtrlGetState($idListViewLeft))
    EndSwitch
WEnd

Of course, when you'll change the path to expand, then you'll have to sort again (or find a quick way to automatically re-sort, it shouldn't be too hard). Files items & folders items will be unfortunately mixed after the sort, which is probably not what the user wants to see, that's something to solve

@WildByDesign is now thinking of reverting to a native listview with its native header. Is it because of the sort issue that seems complicated when the TreeView path changes ?
But imho it will be as hard to solve with a native header or a detached header. It's not because you'll use a native listview that all the sort issues will be automatically solved, they'll be exactly the same (if not mistaken).
After all the work we all did to have this detached header working finally correctly, it would be a pity not to use it and revert to a native listview.

Just my 2 cents...  :)

"I think you are searching a bug where there is no bug... don't listen to bad advice."

Posted
2 hours ago, pixelsearch said:

@WildByDesign is now thinking of reverting to a native listview with its native header. Is it because of the sort issue that seems complicated when the TreeView path changes ?

I've always kind of been experimenting with finding different ways, potentially simpler ways, to get around that WS_EX_COMPOSITED / ListView Header bug. So it just ended up being an experiment that was more simplistic but it was not as robust and nice like the detached header with ListView method.

2 hours ago, pixelsearch said:

But imho it will be as hard to solve with a native header or a detached header. It's not because you'll use a native listview that all the sort issues will be automatically solved, they'll be exactly the same (if not mistaken).

It looks like @Kanashius is going to build the sorting functionality right into the UDF now. So we should be able to call that now with a click on the header once it has been implemented. But you're right, it's going to be tricky either way.

2 hours ago, pixelsearch said:

After all the work we all did to have this detached header working finally correctly, it would be a pity not to use it and revert to a native listview.

I am sticking with the detached header. It's beautiful and functions incredibly well and I feel like we have even more flexibility with the detached header.

2 hours ago, pixelsearch said:

 

Local $hHeader = _GUICtrlListView_GetHeader($idListView)
Local $i_Style_Old = _WinAPI_GetWindowLong($hHeader, $GWL_STYLE)
_WinAPI_SetWindowLong($hHeader, $GWL_STYLE, BitXOR($i_Style_Old, $HDS_BUTTONS))

By the way, the detached header and ListView movement and functionality has been improved after I saw this suggestion from you. It made me realize that I may not need the _WinAPI_SetWindowPos() function within the __WinAPI_Set_Window_Style() function. So I tested it without it and the entire thing is smoother and more responsive. Even reordering the columns didn't need it. :)

Posted (edited)

I noticed a bug in v2.11.1, but I have a feeling it may go back further in releases.

The _clickCallback function in the example always shows the previously clicked item in the ConsoleWrite. It is always one step behind.

I have a feeling that I must have run into this issue before because I set a boolean trigger in _clickCallback which then gets picked up in the main While loop to then pull the correct selection directly from the ListView.

The _selectCallback does provide the correct selection. So the problem only seems to be with _clickCallback.

EDIT: I also noticed right now that the _clickCallback will show a different Item # for the same file:

Click at 0x0000000000220780: D:\Downloads\[228480_6862807.jpg] :92
Click at 0x0000000000220780: D:\Downloads\[228480_6862807.jpg] :91

 

Edited by WildByDesign
Posted

I picked up on a bug related to multiple selections in the ListView:

  • Ctrl + click is clearing the other selected items and only shows one selected item [BUG]
  • Shift + click does work correctly and shows all selected items (no bug here)
  • Mouse click and drag to select also clears selected items and only shows one selected item [BUG]
  • 2 weeks later...
Posted (edited)

I am curious about adding a Type column. Now that you've added the ability to create custom columns it makes this much easier which is nice.

However, do you know if there is an easier way to pull the Type values from the registry?

Eg.:

Type

Folder  File folder
.au3    AutoIt v3 Script
.exe    Application
.dll    Application extension

I know that you have functionality to pull file extension related icons based on registry and so on. So I figured that you might know a way to do this in a more automated way. Thank you. :)

Edited by WildByDesign
  • 3 weeks later...
Posted (edited)

Hey there, after a little winter brake, I am back :)

So, I looked into the sorting with the header and did an implementation there. By default, a simple sorting function is implemented.
For more custom sorting, there is a __TreeListExplorer_SetCallback function, where the $__TreeListExplorer_Callback_ListViewPaths type can be used to provide a function. This is called with a 2D-Array with all drive/folder/filenames before they are put into the ListView. The function can return a 2D-Array, which is then used to fill the ListViews (rows/columns). So the user can get control of all items added to the listview. This returned Array is also used for the default sorting, when it is enabled (when calling __TreeListExplorer_AddView).
Thanks @pixelsearch for the starting pointers there :)

I also fixed the bug with the _clickHandle ( @WildByDesign ). It was related to recent changes, where the click was delayed to handle double clicks and the click callback was called before the click was handled => old data was provided. This is fixed now.

I could not replicated the ctrl+click issue (maybe it was related to the delayed click thingy).
I fixed the Mouse click and drag (Marquee). It works now. Thanks for pointing that one out :).

So, as I mentioned before, there were some larger changes.
1. Because the amount of parameters for 
__TreeListExplorer_AddView got out of control, there is now an additional function: __TreeListExplorer_SetCallback
     All callback parameters of the addView method were moved there and some others were added.
2. The sorting was implemented with an implementation enabled by default (which can be turned of with the new $bEnableSorting parameter at the addView function).
    Clicking at the header sorts by that column, clicking again changes the order. Folders are ALWAYS at the top, files at the bottom.
    Internally not the ListView sorting, but _ArraySort is used (would have had to be done anyway for loading other folders,...).
3. It is possible to add a callback (__TreeListExplorer_Callback_ListViewPaths) to edit the 2D-Array used to fill the ListView.
     The provided array has the format $arPaths[n][1] with only the drive/folder/filenames.
     The callback function should return the required 2D-Array with all the custom columns,... for example an array with the format $arPaths[n][3] for 2 additional columns.
     When setting the callback function, there is an additional parameter to change the column index of the drive/folder/filenames.
     So it is possible to move the drive/folder/filenames to a different column then the first.
4. The $__TreeListExplorer_Callback_ListViewItemCreated stayed and is still called for every created listview item, when set.
    This is done to enable things like putting the filesize in bytes into one column (with the __TreeListExplorer_Callback_ListViewPaths).
    That column can then be used to sort files by bytes (with the integer values) using the default $bEnableSorting option.
    After the listview item is created, the text can then be changed with the ListViewItemCreated callback to represent the short text version e.g. 10MB, 1KB,... 
    This way the files are correctly sorted by the integer size in bytes and not wrongly by the (shortened variant as) strings.
5. The example showcasing most possibilities got a bit complicated, so I added a simpler example for beginners

Happy testing with v2.12 :)

Edited by Kanashius
Posted
On 12/26/2025 at 3:25 PM, WildByDesign said:

However, do you know if there is an easier way to pull the Type values from the registry?

No and the registry has different values, I think, but I took a look at it and found this way:

Local $tSHFILEINFO = DllStructCreate($tagSHFILEINFO)
Local $iAttr = ($bFolder?$FILE_ATTRIBUTE_DIRECTORY:$FILE_ATTRIBUTE_NORMAL)
_WinAPI_ShellGetFileInfo($sAbsolutePath, BitOR($SHGFI_TYPENAME, $SHGFI_USEFILEATTRIBUTES), $iAttr, $tSHFILEINFO)
ConsoleWrite($sAbsolutePath&" >> "&DllStructGetData($tSHFILEINFO, 5)&@crlf)

Hope this helps :)

Posted
34 minutes ago, Kanashius said:

Hope this helps :)

This helps tremendously, thank you.

I am going to test your latest UDF tonight. I’ll have to make some changes in my script regarding the callbacks, but you’ve provided excellent examples so that will be easy.

I have so many ideas flowing right now. :)

Posted (edited)

@Kanashius I have implemented 2.12 into my script and everything is working great. There is one minor bug in the sorting both in my script and in your example. The sorting works, however, it always show the incorrect arrow on the header based on the sort. When the column is sorted descending, the arrow is pointed up. When sorted ascending, the arrow is pointed down. I compared it to File Explorer and Explorer++ and they show the opposite.

I found a way to fix it in my script and the UDF, but you'll have to check and see if it's proper:

First, I set the sort arrow after creating the ListView. Since it is ascending by default, I set it with:

; Set sort arrow
    _GUICtrlHeader_SetItemFormat($g_hHeader, 0, $HDF_SORTUP)

Then in the UDF, I just swapped the positions of the 0 and 1:

If BitAND($iFormat, $HDF_SORTUP) Then ; ascending
    _GUICtrlHeader_SetItemFormat($hHeader, $iCol, BitOR(BitXOR($iFormat, $HDF_SORTUP), $HDF_SORTDOWN))
    $__TreeListExplorer__Data["mViews"][$hView]["mSorting"]["iDir"] = 0
Else ; descending
    _GUICtrlHeader_SetItemFormat($hHeader, $iCol, BitOR(BitXOR($iFormat, $HDF_SORTDOWN), $HDF_SORTUP))
    $__TreeListExplorer__Data["mViews"][$hView]["mSorting"]["iDir"] = 1
EndIf

After that, the sorting (particularly the arrow used) matches what is seen in File Explorer and Explorer++.

22 hours ago, Kanashius said:

I also fixed the bug with the _clickHandle ( @WildByDesign ). It was related to recent changes, where the click was delayed to handle double clicks and the click callback was called before the click was handled => old data was provided. This is fixed now.

Confirmed fixed. Marquee is working great now too. Thank you. :)

22 hours ago, Kanashius said:

I could not replicated the ctrl+click issue (maybe it was related to the delayed click thingy).

So this is an interesting one. The issue is still there. I decided to look into it a bit more this time. For example, let's say you click on one item, then Shift+click further down to select a bunch of items. Those items are selected. Then you hold down Ctrl and select another item. What happens next seems to very much be a timing issue. Everytime I tried this, it would clear the previously selected items and only select the item from the Ctrl+click. But what I noticed is that if you continue to hold Ctrl for a full 1 second after letting the click go, it will keep all of the selections. The problem is, holding Ctrl for a full 1 second after letting go of the click is not typical. So it's definitely something to do with timing. I haven't dug into the code yet but I wonder if IsPressed() with a shorter duration of time can help this or not. Timing issues are complicated though, I understand.

EDIT: I looked into the code a bit more. So it definitely has something to do with timing but also the following line:

_GUICtrlListView_SetItemSelected($hView, $arSel[$j], False)

Commenting out that line fixes the Ctrl+click problem. But I remember as you had mentioned before, that can also cause problems.

Edited by WildByDesign
Posted (edited)

By the way, I have a few things that I wanted to ask.

Func _selectCallback($hSystem, $sRoot, $sFolder, $sSelected)
    GUICtrlSetData($idLabelSelectRight, $sRoot&$sFolder&"["&$sSelected&"]")
    __TreeListExplorer__FileGetIconIndex($sRoot&$sFolder&$sSelected)
    ; ConsoleWrite("Select "&$hSystem&": "&$sRoot&$sFolder&"["&$sSelected&"]"&@CRLF)
EndFunc

I've been curious about this for a while. Your examples going back many releases have always had the __TreeListExplorer__FileGetIconIndex within the _selectCallback function. I just never quite understood it. I had always commented that line out (curiosity) and never noticed any negative effects.

Does __TreeListExplorer__FileGetIconIndex serve as an important part of the select callback?

 

Also, I have a weird issue where it wouldn't let me add a 4th column as custom columns. I did find a way to work around the issue. But I'm just not sure why it didn't work the regular way. By the way, you can check the latest Files Au3 sources updated this morning in the Files Au3 thread to see if you have a moment.

I added the Type column to the ListView (I ended up removing it in sources since it did not work):

$idListview = GUICtrlCreateListView("Name|Size|Date Modified|Type", 0, $iHeaderHeight, $aWinSize2[0], $aWinSize2[1] - $iHeaderHeight - $sRefreshPosV - $iTopSpacer, BitOR($LVS_SHOWSELALWAYS, $LVS_NOCOLUMNHEADER), BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER, $LVS_EX_TRACKSELECT))

There is a callback to custom columns which works (except for the 4th column, technically col3):

__TreeListExplorer_SetCallback($idListview, $__TreeListExplorer_Callback_ListViewItemCreated, "_handleCustomColumns")

And here is what that function looks like:

Func _handleCustomColumns($hSystem, $hView, $sPath, $sFilename, $iIndex, $bFolder)
    If StringRight($sFilename, 1)<>":" Then ; do not for drives
        If $bFolder Then
            _GUICtrlListView_SetItemText($hView, $iIndex, __TreeListExplorer__GetTimeString(FileGetTime($sPath, 0)), 2)
            _GUICtrlListView_SetItemText($hView, $iIndex, _getFolderInfo($sPath), 3)
        Else
            _GUICtrlListView_SetItemText($hView, $iIndex, __TreeListExplorer__GetSizeString(FileGetSize($sPath)), 1)
            _GUICtrlListView_SetItemText($hView, $iIndex, __TreeListExplorer__GetTimeString(FileGetTime($sPath, 0)), 2)
            _GUICtrlListView_SetItemText($hView, $iIndex, _getFileType($sPath), 3)
        EndIf
    EndIf
EndFunc

Func _getFolderInfo($sPath)
    Local $tSHFILEINFO = DllStructCreate($tagSHFILEINFO)
    Local $iAttr = $FILE_ATTRIBUTE_DIRECTORY
    _WinAPI_ShellGetFileInfo_mod($sPath, BitOR($SHGFI_TYPENAME, $SHGFI_USEFILEATTRIBUTES), $iAttr, $tSHFILEINFO)
    Return DllStructGetData($tSHFILEINFO, 5)
EndFunc

Func _getFileType($sPath)
    Local $tSHFILEINFO = DllStructCreate($tagSHFILEINFO)
    Local $iAttr = $FILE_ATTRIBUTE_NORMAL
    _WinAPI_ShellGetFileInfo_mod($sPath, BitOR($SHGFI_TYPENAME, $SHGFI_USEFILEATTRIBUTES), $iAttr, $tSHFILEINFO)
    Return DllStructGetData($tSHFILEINFO, 5)
EndFunc

It's like it never creates the Type column in the ListView or fills it.

What I realized is that it only works if I add it later in the scripts (after the callbacks are set):

; add listview column for Type (for some reason this only works when added later)
_GUICtrlListView_AddColumn($g_hListview, "Type", 150)

So without that line, it will never fill col3 (Type column). I don't quite understand why adding that column manually after the callbacks works. It's a mystery. But thankfully I have that as a workaround.

EDIT: I am guessing that it has something to do with me not resizing the array, possibly?

I noticed that you do that in your newer _handleListViewData() function and return the array at the end.

Edited by WildByDesign
Posted
11 hours ago, WildByDesign said:

The sorting works, however, it always show the incorrect arrow on the header based on the sort. When the column is sorted descending, the arrow is pointed up. When sorted ascending, the arrow is pointed down. I compared it to File Explorer and Explorer++ and they show the opposite.

Yeah, I did the arrow orientation with my own thoughts and did not check what the explorer is doing. I changed that for the next update to match it to the explorer. Thanks for noticing :)

 

11 hours ago, WildByDesign said:

So this is an interesting one. The issue is still there. I decided to look into it a bit more this time. For example, let's say you click on one item, then Shift+click further down to select a bunch of items. Those items are selected. Then you hold down Ctrl and select another item. What happens next seems to very much be a timing issue. Everytime I tried this, it would clear the previously selected items and only select the item from the Ctrl+click. But what I noticed is that if you continue to hold Ctrl for a full 1 second after letting the click go, it will keep all of the selections. The problem is, holding Ctrl for a full 1 second after letting go of the click is not typical. So it's definitely something to do with timing. I haven't dug into the code yet but I wonder if IsPressed() with a shorter duration of time can help this or not. Timing issues are complicated though, I understand.

Hmmm... do you have that problem in your FilesAu3 or also in my examples?
I checked and tried clicking a lot and also followed your description, but I could not replicate that (Win11/AutoIt 3.3.18.0).
So I am a bit at a loss how to fix that. Maybe you can share your setup so I may look into replicating that.

But yeah, removing

_GUICtrlListView_SetItemSelected($hView, $arSel[$j], False)

will disable the deselection completly, even if it should be done, so that is not the solution.

 

9 hours ago, WildByDesign said:

Does __TreeListExplorer__FileGetIconIndex serve as an important part of the select callback?

Nope, I use the example for testing and accidentally forgot to remove that line. So it was just for me testing the GetIconIndex method. I removed it for the next update.

 

9 hours ago, WildByDesign said:

Also, I have a weird issue where it wouldn't let me add a 4th column as custom columns. I did find a way to work around the issue. But I'm just not sure why it didn't work the regular way.

Disabling the default columns when adding the listview to the TLE system should fix the missing columns. When Default columns are used, all existing columns are deleted and replaced with the default ones. So setting the parameter $bLVDefaultColumns to False should fix that for you :) 
 

; From
__TreeListExplorer_AddView($hTLESystem, $idListview, True, True, True, False)
; To
__TreeListExplorer_AddView($hTLESystem, $idListview, True, True, True, False, False)

With the recent changes, the "proper" way for adding custom columns would be using the $__TreeListExplorer_Callback_ListViewPaths callback and return the different columns there, as you can see in the example.
As you are using the default sorting method from the udf, this would also allow sorting of columns where the data is added by yourself.
The callback $__TreeListExplorer_Callback_ListViewPaths is called BEFORE the array (later listview items) are sorted.
The callback $__TreeListExplorer_Callback_ListViewItemCreated is called AFTER the listview was filled with all items (and subitems) and can be used to do some adjustments to the created (and sorted) listview items.
E.g. This can be used to put the filesize as integer into the array, do the sorting on the integer values and use the $__TreeListExplorer_Callback_ListViewItemCreated callback to convert those to their string representation, when they are already in the listview (this is invisible to the user, as visible updates to the listview are disabled during this. (ListView StartUpdate/EndUpdate)).

Thank you for pointing out the issues @WildByDesign and I hope I could help you :)

Posted
12 hours ago, Kanashius said:

Hmmm... do you have that problem in your FilesAu3 or also in my examples?
I checked and tried clicking a lot and also followed your description, but I could not replicate that (Win11/AutoIt 3.3.18.0).
So I am a bit at a loss how to fix that. Maybe you can share your setup so I may look into replicating that.

It happens in Files Au3 and it also happens in your example as well. Both. I will probably have to get back to you on this one once I can figure out some more details to help reproduce it. My setup is also Win11 with the latest AutoIt 3.3.18.0. I think what I might do is put together an animated Gif or MP4 or something to show. But I want to see if I can add some ConsoleWrite's or something to get more info. So I will follow up more on this later.

12 hours ago, Kanashius said:

Disabling the default columns when adding the listview to the TLE system should fix the missing columns. When Default columns are used, all existing columns are deleted and replaced with the default ones. So setting the parameter $bLVDefaultColumns to False should fix that for you :) 

You're right, I completely missed the $bLVDefaultColumns parameter in the function. Your functions are all very well structured and your code comments are great too. So that is totally my mistake for missing that one.

12 hours ago, Kanashius said:

The callback $__TreeListExplorer_Callback_ListViewPaths is called BEFORE the array (later listview items) are sorted.
The callback $__TreeListExplorer_Callback_ListViewItemCreated is called AFTER the listview was filled with all items (and subitems) and can be used to do some adjustments to the created (and sorted) listview items.

That description really help a lot. I was initially confused about how exactly those were supposed to work. I completely understand it now.

12 hours ago, Kanashius said:

Thank you for pointing out the issues @WildByDesign and I hope I could help you :)

You're welcome. Your help is always thorough and very beneficial. Thank you for everything as well. :)

Posted

@Kanashius I have an idea for the sorting. I like the simple sorting because it works well. And I like the folders being at the top.

However, when you do a sort within a directory that has a lot of folders, it gives the impression that the sort is broken. Just because the folders at the top remain the same. So visually, you can't tell that a sort occurred until you scroll down past the folders.

What do you think about keeping the folders at the top (as it is), but sort those folders A-Z (and Z-A) when performing a sort?

The folders would remain at the top still but the folders themselves would also sort.

Posted

Hmmm.... I thought about this and I like the idea.
The problem I see is, that I would have to check if the order of the folders changed (to apply this change, only if they are not reordered). I do not know, which columns will be added by the developers using the UDF. It could be the same for some folders, but different for others,...
This would require additional checks (computational overhead) or a custom _ArraySort implementation with less overhead (but still a little)... which is a lot of work for this and may not even be desired.
Thats why I would decide against that as the default for the UDF. Especially, because it may be undesired behaviour for some applications.

If wou would like that feature for your UDF, you should probably disable the default $bEnableSorting when adding the view and do that yourself, you already have the WM_NOTIFY listeners,... setup, so it shouldn't be to hard (with the UDF as example, you already quoted most of the required code from the end of the __TreeListExplorer__WinProc function).
Then just put an _ArraySort at the end of the $__TreeListExplorer_Callback_ListViewPaths callback and you are done :)

Posted
13 hours ago, Kanashius said:

This would require additional checks (computational overhead) or a custom _ArraySort implementation with less overhead (but still a little)... which is a lot of work for this and may not even be desired.

I completely respect your decision and understand why. The added complexity but particularly the added overhead would certainly not be desirable as a default.

13 hours ago, Kanashius said:

If wou would like that feature for your UDF, you should probably disable the default $bEnableSorting when adding the view and do that yourself, you already have the WM_NOTIFY listeners,... setup, so it shouldn't be to hard (with the UDF as example, you already quoted most of the required code from the end of the __TreeListExplorer__WinProc function).
Then just put an _ArraySort at the end of the $__TreeListExplorer_Callback_ListViewPaths callback and you are done :)

Indeed, yes. You have designed it in such an intelligent way so that anyone using the UDF can easily extend the sorting capabilities by using their own custom code. You have an excellent way of thinking ahead. :)

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