WildByDesign Posted December 21 Author Posted December 21 FilesAu3-2025-12-21: Please keep in mind that in this release, there are minor changes to the GUIFrame UDF. Sometimes I've made small adjustments to some of the other UDF script files as well. So anytime there is a new release, you will need to overwrite all of the Files Au3 script files and not just the main FilesAu3 script. Updated detached Header / ListView synchronization code from @pixelsearch Added color to header divider when tracking or double-clicking divider Fixed issue where moving separator would show cursor changes and/or highlighting of controls See my GUIFrame UDF post for more info (fixed with _WinAPI_SetCapture on separator) Something that I may try to look into next is indentation of the ListView items. But I would have to do that from within the TreeListExplorer UDF (I think) and I'm not even certain if it would look good or not. I'm just curious about trying to see if it looks good or makes sense. I am also curious to look into renaming of files/folders in the ListView. I've tested it partially and is interesting. It's also something that I can add to expand the features in the ListView context menu.
pixelsearch Posted December 22 Posted December 22 (edited) @WildByDesign hello I got a couple of comments : 1) Func _resizeHeaderItems is never called, so it should be deleted from the script. It was used in early releases during Case $LVN_ENDSCROLL but it has been replaced now with _resizeLVCols2() 2) Your function _resizeHeader ; Func _resizeHeader() ; triggered from main loop when events $GUI_EVENT_RESIZED or $GUI_EVENT_MAXIMIZE occur ; resize header to match listview width $aWinSize2 = WinGetClientSize($hChildLV) _WinAPI_SetWindowPos_mod($g_hHeader, 0, 10, 0, $aWinSize2[0] - 11, $iHeaderHeight, BitOR($SWP_NOZORDER, $SWP_NOACTIVATE)) EndFunc This code can't work correctly for the following reason : if the listview got a horizontal scrollbar which is not at its very left position, then you can't simply move the detached header to a static position of 10, 0 and ignore the negative values found in the leftmost LV column(s) rectangle(s). Doing so will not align the headers items with the listview columns, until you scroll horizontally by yourself, later. So I suggest you get rid of the _resizeHeader() function and instead of this... While True Local $iMsg = GUIGetMsg() Switch $iMsg ... Case -12, -6 ; $GUI_EVENT_RESIZED, $GUI_EVENT_MAXIMIZE ; resize header to match listview width _resizeHeader() ...you could simply use this : While True Switch GUIGetMsg() ... Case $GUI_EVENT_RESIZED _resizeLVCols2() The function _resizeLVCols2 seems to solve this issue nicely. Later, if you find cases where $GUI_EVENT_MAXIMIZE or $GUI_EVENT_RESTORE need to be added to the Case line, then it will be time to add them. For now, if not mistaken, $GUI_EVENT_RESIZED seems to be enough (quickly tested) This should solve the alignment issues happening when enlarging the GUI or moving Melba23's vertical separator between frames (both actions triggering $GUI_EVENT_RESIZED) I'm not sure at all it will solve your other issue that happens randomly and only in dark mode (can't test that) when you track the header dividers. Could it be a timer issue as found in the 3 functions _removeExStyles() _addExStyles() _resetExStylesAdlib() ? Can't you run the script in dark mode without any timer and not removing/adding styles like $WS_EX_COMPOSITED and see if it solves your issue ? When you have this issue, can't you test what happens if you modify your 750ms delay ? Or even in dark mode, try to bypass $NM_CUSTOMDRAW and don't use it, is the issue still there ? Case $NM_CUSTOMDRAW If $isDarkMode Then... Maybe you already tested all this, just to make sure. Because if you can't be sure of the part of the code that creates the issue, then it will be hard for you to debug it, especially you use 3-4 external big UDF's For the record, I see this in your code : Case $HDN_TRACK, $HDN_TRACKW ... If $isDarkMode Then _addExStyles() EndIf If you comment out these 3 lines (also found in your Case $HDN_ENDTRACK, $HDN_ENDTRACKW) do you still have an alignment issue in dark mode while tracking the headers items ? If the issue disappear when you don't alter the styles during tracking in dark mode, then the function _addExStyles and the Adlib create the issue, what do you think ? Good luck Edit: now that you added a Case $HDN_ENDTRACK, $HDN_ENDTRACKW, shouldn't it contain the line _resizeLVCols2() as found in Case $HDN_TRACK, $HDN_TRACKW ? Who knows, maybe it could solve your issue, fingers crossed. Edited December 23 by pixelsearch added edit comment WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Tuesday at 12:05 PM Author Posted Tuesday at 12:05 PM 11 hours ago, pixelsearch said: 1) Func _resizeHeaderItems is never called, so it should be deleted from the script. It was used in early releases during Case $LVN_ENDSCROLL but it has been replaced now with _resizeLVCols2() Yes, good point. This can certainly be removed. 11 hours ago, pixelsearch said: This code can't work correctly for the following reason : if the listview got a horizontal scrollbar which is not at its very left position, then you can't simply move the detached header to a static position of 10, 0 and ignore the negative values found in the leftmost LV column(s) rectangle(s). Doing so will not align the headers items with the listview columns, until you scroll horizontally by yourself, later. Speaking of the Header and ListView being 10 pixels in from the left. I did initially have some problems with that. I was able to solve the problem but since you know how the code in the _resizeLVCols2() functions works more intimately, I would like to know what you think and also if it can potentially cause any problems. ... WinMove($g_hHeader, "", $aRectLV[0] + 10, 0, WinGetClientSize($g_hChild)[0] - $aRectLV[0], Default) ... WinMove($g_hHeader, "", 0 + 10, 0, WinGetClientSize($g_hChild)[0], Default) ... When I added your updated code to Files Au3 a few days ago, I had to add the + 10 to both WiinMove functions. It seemed to solve the problem of it moving to 0 x. I just don't know if it causes any incorrect measurements on the right side. 11 hours ago, pixelsearch said: ...you could simply use this : While True Switch GUIGetMsg() ... Case $GUI_EVENT_RESIZED _resizeLVCols2() This is a great suggestion. Your function is definitely the most appropriate there. I did notice that maximize would not trigger the resize though, so I had to add $GUI_EVENT_MAXIMIZE to it. 11 hours ago, pixelsearch said: If you comment out these 3 lines (also found in your Case $HDN_ENDTRACK, $HDN_ENDTRACKW) do you still have an alignment issue in dark mode while tracking the headers items ? No, commenting out these 3 lines does solve the issue. 11 hours ago, pixelsearch said: Edit: now that you added a Case $HDN_ENDTRACK, $HDN_ENDTRACKW, shouldn't it contain the line _resizeLVCols2() as found in Case $HDN_TRACK, $HDN_TRACKW ? During my desperate attempts to fix the dark mode header issues, I had removed _resizeLVCols2() from there. The issue triggered far more often with _resizeLVCols2() in general. Keep in mind, dark mode only. Light mode behaves perfectly. It seemed that the more code in there, the more often it would trigger the problem. Less code, the problem would trigger much less often. At one point, I thought it solved the problem by removing _resizeLVCols2(). But unfortunately it did not solve it. It just became harder to trigger. 11 hours ago, pixelsearch said: When you have this issue, can't you test what happens if you modify your 750ms delay ? Or even in dark mode, try to bypass $NM_CUSTOMDRAW and don't use it, is the issue still there ? This was one of my tests a few days ago by trying to rule out the timers. Eventually, I did a test by keeping WS_EX_COMPOSITED on the entire time just to rule out the timing of extended style adding/removal. Anyway, I can confirm it is not related to the timers or general timing of adding/removal of exstyles. 12 hours ago, pixelsearch said: I'm not sure at all it will solve your other issue that happens randomly and only in dark mode (can't test that) when you track the header dividers. Could it be a timer issue as found in the 3 functions _removeExStyles() _addExStyles() _resetExStylesAdlib() ? Can't you run the script in dark mode without any timer and not removing/adding styles like $WS_EX_COMPOSITED and see if it solves your issue ? So I did unfortunately end up getting to the root of the issue. The incompatibility is the combination of WS_EX_COMPOSITED and the subclassing of the detached header. The problem is, though, without WS_EX_COMPOSITED, the resizing of header items flickers like crazy between the original black text and the white text while the subclassing tries to keep up with it. The WS_EX_COMPOSITED actually did a fantastic job of smoothing that out with zero flicker during movement. It visually appeared perfect and functioned perfectly. Until, of course, that approx. 5% of the time where the header item sizes end of mismatching the ListView column sizes. I'm kind of at a dead end with that right now. Dark mode is pretty important. I feel like it's always good to provide a light mode and dark mode so that users have choice. But as always, I have one last idea. I have a few more things to workout before I can present the idea.
WildByDesign Posted Tuesday at 02:29 PM Author Posted Tuesday at 02:29 PM (edited) I have a pretty well-functioning prototype that solves the issues with the dark mode header. This is just a testing example right now, so please extract into its own separate directory. The GUIFrame*.au3 UDF has been modified and runs some commands from within it. Anyone interested can certainly feel free to test it and give feedback. However, most importantly, @pixelsearch if you have a moment I would really like your opinion and feedback as well. I understand that you have some concerns about the amount of work that you put into the detached header and were bothered by the fact that it may go to waste. I just want to assure you that all of that detached header work is still 100% necessary and fabulous. Especially the _resizeLVCols2() function which does some legitimate magic. I'm afraid to count the amount of hours that it took me over the past week or more to get it working right. Particularly, ensuring that the detached header and ListView header were 100% visually equal. But I didn't give up and got it working with DPI and all. What is happening? When you move the separator, it simply hides the LV header and shows the detached header briefly. At the same time, it moves the LV down by the height of the header and places it back right after. There is no visual difference when this all occurs. Essentially, the LV header would be the one which the user interacts with to resize columns, sort, etc. The detached header shows its pretty face when needed and continues to resize itself to match the LV header sizing. Problems? So far, the only visual difference that I notice is that the LV scrollbar has a single flicker at the start of the separator movement. There is also a noticeable movement of the LV scrollbar at the start of the separator movement where the scrollbar goes down by the height of the header. When the separator movement stops, the scrollbar moves back up. Those things are subtle but I will try to smooth it out more. There is an occasional flicker of the ListView when at the end of movement. Maybe 1 out of 10 times. But it's very subtle. I probably just need to change the order of extended style restoration in the _resetExStylesAdlib() function. TO DO? Since the LV header would now have the responsibility of handling the column resizing, sorting, etc. I will have to move that functionality over in the WM_NOTIFY function. For example: Case $g_hListView Switch $iCode Case $LVN_ENDSCROLL Local Static $tagNMLVSCROLL = $tagNMHDR & ";int dx;int dy" Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $tNMLVSCROLL.dy = 0 Then ; ListView horizontal scrolling _resizeLVCols2() EndIf Case $LVN_COLUMNCLICK ; A column was clicked ConsoleWrite("column was clicked." & @CRLF) ; we can use this to initiate column sorting ; TO DO: need to know column number that was clicked _GUICtrlListView_SortItems($g_hListview, 0) EndSwitch I would like to use $LVN_COLUMNCLICK to handle the sorting which seems to do the job. However, I don't know how to get the column number yet and haven't really looked that far into it. So at the moment, if you click on any of the LV header items, it will sort column 0. Thoughts and opinions? My own impression with this is that the LV column resizing/tracking is much smoother. Separator movement is slick and smooth. This is especially better for dark mode since I wasn't able to figure out how to fix the dark mode header issue between WS_EX_COMPOSITED and the subclassing. It was kind of a dead end for dark mode. Anyway, I would really like some opinions and feedback on this method. Particularly @pixelsearch since the detached header is your handiwork. It's not going anywhere. Edited Wednesday at 11:17 AM by WildByDesign failed experiment
pixelsearch Posted Tuesday at 05:56 PM Posted Tuesday at 05:56 PM 3 hours ago, WildByDesign said: . I understand that you have some concerns about the amount of work that you put into the detached header and were bothered by the fact that it may go to waste. I just want to assure you that all of that detached header work is still 100% necessary and fabulous. Especially the _resizeLVCols2() function which does some legitimate magic. On 12/1/2025 at 4:23 PM, pixelsearch said: The problem with a separate header control is that you'll have to add plenty of code in your script to get (nearly) the same results as a native Listview control (which takes care of its native header items), this means sorting listview columns by clicking their headers, changing header items order by dragging a header item at the left or right of another, double-clicking a header separator etc...) [...] Of course all these points could be fixed with additional code, it's up to you to decide if you're ready to add all this code to avoid flicker. I warned you 3 weeks ago The new version "FilesAu3-testHeaderV2.au3" doesn't run on my computer, don't ask me why. It just hangs and I got to use the Task manager to kill the AutoIt process. Tried it twice, no big deal. I notice you started to use, for test, a native listview (without $LVS_NOCOLUMNHEADER) so you shouldn't need any of the functions and notifications related to the detached header. If you're going this way (maybe for test only) why not creating another script, without any part concerning the detached header and see where it goes ? Wouldn't it be clearer for you to completely separate the scripts, one with a detached header, the other one without it and remove all code related to it ? Now yout question about sorting using the LVN_COLUMNCLICK notification code : you'll find the code for this in the help file, topic _GUICtrlListView_SortItems, which indicates the 2 possible ways for sorting (example 1 without LVN_COLUMNCLICK is easier, example 2 uses LVN_COLUMNCLICK as in your last script) Good luck "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Tuesday at 07:06 PM Author Posted Tuesday at 07:06 PM 1 hour ago, pixelsearch said: The new version "FilesAu3-testHeaderV2.au3" doesn't run on my computer, don't ask me why. It just hangs and I got to use the Task manager to kill the AutoIt process. Tried it twice, no big deal. How can we determine what part of the code is causing it to crash on your computer? If we know that, then I can fix it. I really wish that you could try this one successfully to see how well it works. 1 hour ago, pixelsearch said: I notice you started to use, for test, a native listview (without $LVS_NOCOLUMNHEADER) so you shouldn't need any of the functions and notifications related to the detached header. Good point. I will remove the unused functions. 1 hour ago, pixelsearch said: If you're going this way (maybe for test only) why not creating another script, without any part concerning the detached header and see where it goes ? Wouldn't it be clearer for you to completely separate the scripts, one with a detached header, the other one without it and remove all code related to it ? That's actually a really great idea. I don't know how far either one will end up going. So I can consider it like a fork and keep both methods up-to-date for now. I like that idea. 1 hour ago, pixelsearch said: Now yout question about sorting using the LVN_COLUMNCLICK notification code : you'll find the code for this in the help file, topic _GUICtrlListView_SortItems, which indicates the 2 possible ways for sorting (example 1 without LVN_COLUMNCLICK is easier, example 2 uses LVN_COLUMNCLICK as in your last script) Excellent, thank you. I went with the first example because it was quite simple and it works well.
WildByDesign Posted Tuesday at 07:34 PM Author Posted Tuesday at 07:34 PM 1 hour ago, pixelsearch said: The new version "FilesAu3-testHeaderV2.au3" doesn't run on my computer, don't ask me why. It just hangs and I got to use the Task manager to kill the AutoIt process. Tried it twice, no big deal. My first thought was maybe it requires x64 AutoIt to run. I don’t have that specified in the script but I know that my setup runs x64 AutoIt by default.
WildByDesign Posted Wednesday at 11:19 AM Author Posted Wednesday at 11:19 AM Just a quick note that testHeaderV2 was a failed experiment. Too problematic.
WildByDesign Posted Friday at 12:36 AM Author Posted Friday at 12:36 AM (edited) FilesAu3-2025-12-25: This release doesn't have any new features added. The only significant changes here relate to making the header divider movement smoother. In particular, the dark mode subclassed header had issues that was causing some flickering and misalignment between the detached header and the ListView. @pixelsearch The updated source archive is in the first post, but I wanted to share some of the changes. The overall header movement became smoother. Particularly important for dark mode, but light mode has smoother movement as well. I had to change: $g_hHeader = _GUICtrlHeader_Create($hChildLV, BitOR($HDS_BUTTONS, $HDS_HOTTRACK, $HDS_DRAGDROP)) To: $g_hHeader = _GUICtrlHeader_Create($hChildLV, BitOR($HDS_BUTTONS, $HDS_DRAGDROP, $HDS_FULLDRAG)) The HDS_FULLDRAG allowed for much smoother movement of the header divider. However, it is known that HDS_HOTTRACK does not work with HDS_FULLDRAG. HDS_FULLDRAG is default for a header that is attached to a ListView. Therefore, the Case $HDN_TRACK, $HDN_TRACKW was removed and replaced with the following: Case $HDN_ITEMCHANGING, $HDN_ITEMCHANGINGW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item Local $tHDITEM = DllStructCreate($tagHDITEM, $tNMHEADER.pItem) Local $iHeaderItemWidth = $tHDITEM.XY Local $tRECT, $iHeaderColWidth $tRECT = _GUICtrlHeader_GetItemRectEx($g_hHeader, $iHeaderItem) $iHeaderColWidth = DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") _GUICtrlListView_SetColumnWidth($g_hListview, $iHeaderItem, $iHeaderColWidth) _resizeLVCols2() Return False ; to continue tracking the divider Case $HDN_ITEMCHANGED, $HDN_ITEMCHANGEDW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item Local $tHDITEM = DllStructCreate($tagHDITEM, $tNMHEADER.pItem) Local $iHeaderItemWidth = $tHDITEM.XY Local $tRECT, $iHeaderColWidth $tRECT = _GUICtrlHeader_GetItemRectEx($g_hHeader, $iHeaderItem) $iHeaderColWidth = DllStructGetData($tRECT, "Right") - DllStructGetData($tRECT, "Left") _GUICtrlListView_SetColumnWidth($g_hListview, $iHeaderItem, $iHeaderColWidth) _resizeLVCols2() EDIT: I just realized that I can combine the two Cases above since the functions within are identical. I ran some performance testing on _GUICtrlHeader_GetItemWidth(), _GUICtrlHeader_GetItemRect() and _GUICtrlHeader_GetItemRectEx(). I ended up going with _GUICtrlHeader_GetItemRectEx() because it was twice as fast as the other two. The reason why I ended up measuring the header item was because $tHDITEM.XY was occasionally providing an incorrect value (dark mode only) which was a big part of the problem. EDIT2: I have to correct myself. Now that WS_EX_COMPOSITED isn't required anymore divider movement in dark mode, $tHDITEM.XY is providing the correct values and I can go back to using that which should be a bit more efficient. That is where the issue was before, WS_EX_COMPOSITED was causing occasional incorrect values from $tHDITEM.XY which would cause the misalignment issues. That was the source of the issue. It is no longer an issue now with HDS_FULLDRAG. Bonus: Here is the best part. For whatever reason, this new method does not mess with the dark mode header text and therefore does not require modifying the extended styles at all while the header is moving. I was kind of shocked and surprised when I realized this. No WS_EX_COMPOSITED required anymore for divider movement (dark mode). Case $HDN_DIVIDERDBLCLICK, $HDN_DIVIDERDBLCLICKW did still need the brief modification of extended styles still, though. Dark mode only of course. Anyway, give it a try when you get a chance. The divider movement is so much more efficient and therefore smoother in my experience. Let me know what you think. Edited Friday at 01:09 AM by WildByDesign pixelsearch 1
pixelsearch Posted Friday at 08:25 AM Posted Friday at 08:25 AM (edited) @WildByDesign great changes, it sure looks better now imho there is no need to check HDN_ITEMCHANGING. The script has already plenty to do, no need of extra work. You would need HDN_ITEMCHANGING for example to prevent that an attribute of the item is about to change, by returning True and won't let it change. Placing a counter inside both Case (ITEMCHANGING and ITEMCHANGED) will show you that there are called dozen of times (and both the same number of times) when you move the divider a couple of millimeters. So HDN_ITEMCHANGED should be enough : I just checked and it worked very fine with only HDN_ITEMCHANGED. 20 hours ago, WildByDesign said: The reason why I ended up measuring the header item was because $tHDITEM.XY was occasionally providing an incorrect value (dark mode only) which was a big part of the problem. This is really strange, it means that $tHDITEM.XY is different from $iHeaderColWidth from time to time. If I were you, I'd place a counter at the very end of Case $HDN_ITEMCHANGED , to check how many times it happens, something like : Case $HDN_ITEMCHANGED ... Local Static $iCounter = 0 $iCounter += 1 If $tHDITEM.XY <> $iHeaderColWidth Then ConsoleWrite("$iCounter = " & $iCounter & " $tHDITEM.XY = " & $tHDITEM.XY & " $iHeaderColWidth = " & $iHeaderColWidth & @crlf) EndIf 20 hours ago, WildByDesign said: HDS_FULLDRAG is default for a header that is attached to a ListView. That's very interesting to know, thanks for the information ! 2 things I changed in my version of _resizeLVCols2() 1) Deleted the following line, which created issues in the script I'll present below. The line was commented as "experimental"... If $iX_Old = $aRectLV[0] Then Return ; no need to move/resize the detached header in this case (experimental, to be confirmed) 2) Both WinMove($g_hHeader ...) use now WinGetPos(...)[2] instead of WinGetClientSize(...)[0] Concerning this line : $idListview = GUICtrlCreateListView("Name|Size|Date Modified", 10, ... That was a challenge to me, because imagine what could happen if you choosed 50 instead of 10, then your LV would appear like this, as soon as you start to scroll a bit to the right : You probably already noticed this is happening in your script, the little gap on the left side of LV when you added 10 to x, no matter you indicated it 3 times in the script (once when defining the LV, 2 other times inside the function _resizeLVCols2) In fact, as soon as the LV got a margin inside the child window, this problem will appear and it's not easy to solve. When the LV got exactly the same width as the child window, then the problem disappears. That's why I finished the following script yesterday with a detached header and added everything I could to minimize flicker in the LV while resizing the Gui (which makes the LV resizes too of course) You'll notice an additional frame which contains the header, so even if you indicate (for x coord) 50 instead of 10 in this line... Local $aLV[4] = [10, ... ...then you'll notice the header is well contained inside its frame and nothing expands on the left side. Please be kind to test the script quickly and let me know if it flickers or not on your computer. I'd like to keep it as a canvas for the scripts to come, when a listview is used in a resizable GUI and the user would like to avoid flicker. expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiImageList.au3> #include <GuiListView.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> Opt("MustDeclareVars", 1) Global $g_hGUI, $g_hChild, $g_hFrameHeader, $g_hHeader, $g_hListview Global $g_idDummyEndDrag, $g_iHeaderHeight, $g_iIconWidth, $g_nRatio[4] Example() ;============================================== Func Example() $g_iHeaderHeight = _CheckHeaderHeight() Local $sLVcoldef, $bIcons = True, $iColWidth = 140, $nRows = 30, $nCols = 10 ; <======= test different values here Local $aGui[4] = [400, 400, -1, -1] ; W, H, X, Y Local $aChild[4] = [320, 320, 40, 40] ; W, H, X, Y Local $aLV[4] = [10, 10 + $g_iHeaderHeight, $aChild[0] - 20, $aChild[1] - $g_iHeaderHeight - 20] ; X, Y, W, H $g_hGUI = GUICreate("Detached header control #4", $aGui[0], $aGui[1], $aGui[2], $aGui[3], $WS_OVERLAPPEDWINDOW, $WS_EX_TOPMOST) GUISetBkColor(0x808080) ; grey $g_idDummyEndDrag = GUICtrlCreateDummy() $g_hChild = GUICreate("ChildWindow", $aChild[0], $aChild[1], $aChild[2], $aChild[3], $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0x606060) ; darker grey ;;;;;;;;;;;;;;;;;;; $g_hFrameHeader = GUICreate("FrameHeader", $aLV[2], $g_iHeaderHeight, $aLV[0], $aLV[1] - $g_iHeaderHeight, $WS_CHILD, -1, $g_hChild) $g_hHeader = _GUICtrlHeader_Create($g_hFrameHeader, BitOR($HDS_BUTTONS, $HDS_FULLDRAG, $HDS_DRAGDROP)) For $i = 0 To $nCols - 1 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, $iColWidth) $sLVcoldef &= $i & "|" ; no problem with last superfluous "|" Next ;;;;;;;;;;;;;;;;;;; GUISwitch($g_hChild) Local $idListview = GUICtrlCreateListView($sLVcoldef, $aLV[0], $aLV[1], $aLV[2], $aLV[3], _ BitOR($GUI_SS_DEFAULT_LISTVIEW, $LVS_NOCOLUMNHEADER)) ; _GUICtrlListView_SetExtendedListViewStyle($idListview, BitOr($LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER)) $g_hListview = GUICtrlGetHandle($idListview) ; WinSetState(_GUICtrlListView_GetHeader($idListview), "", @SW_DISABLE) ; <============================ useful ? If $bIcons Then Local $hImageList = _GUIImageList_Create(20, 20, 5) ; 20,20 = width/height (pixels) of each image/icon . 3rd param. 5 for 32 bits. For $i = 0 To $nRows - 1 _GUIImageList_AddIcon($hImageList, @SystemDir & "\shell32.dll", $i + 204) Next _GUICtrlListView_SetImageList($idListview, $hImageList, 1) ; 1 = image list with small icons EndIf _GUICtrlListView_BeginUpdate($idListview) For $i = 0 To $nRows - 1 _GUICtrlListView_AddItem( $idListview, "item" & $i & "-000000000Z", ($bIcons ? $i : -1) ) For $j = 1 To $nCols _GUICtrlListView_AddSubItem($idListview, $i, "row" & $i & "-" & "col" & $j, $j) Next Next _GUICtrlListView_EndUpdate($idListview) ; resize listview columns to match header widths + update global variable $g_iIconWidth _resizeLVCols() GUISetState(@SW_SHOW, $g_hGUI) GUISetState(@SW_SHOW, $g_hChild) GUISetState(@SW_SHOW, $g_hFrameHeader) ; compute 4 ratios to resize the child window while resizing the Gui $g_nRatio[0] = $aChild[2] / $aGui[0] ; Child X / Parent W $g_nRatio[1] = $aChild[3] / $aGui[1] ; Child Y / Parent H $g_nRatio[2] = $aChild[0] / $aGui[0] ; Child W / Parent W $g_nRatio[3] = $aChild[1] / $aGui[1] ; Child H / Parent H _GUICtrlListView_RegisterSortCallBack($idListView, 2) ; 2 = natural sort $__g_aListViewSortInfo[1][10] = $g_hHeader ; hack to add a sort arrow (use only with a "detached" header !) GUIRegisterMsg($WM_ENTERSIZEMOVE, "WM_ENTERSIZEMOVE") GUIRegisterMsg($WM_EXITSIZEMOVE, "WM_EXITSIZEMOVE") GUIRegisterMsg($WM_SIZE, "WM_SIZE") GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $g_idDummyEndDrag _reorderLVCols() EndSwitch WEnd _GUICtrlListView_UnRegisterSortCallBack($idListView) _GUICtrlHeader_Destroy($g_hHeader) GUIDelete($g_hFrameHeader) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example ;============================================== Func _CheckHeaderHeight() Local $hGUI_Temp = GUICreate("Check header height", 200, 100) Local $hHeader_Temp = _GUICtrlHeader_Create($hGUI_Temp) Local $iHeight = _WinAPI_GetWindowHeight($hHeader_Temp) ; checked to take care of each user's DPI settings _GUICtrlHeader_Destroy($hHeader_Temp) GUIDelete($hGUI_Temp) Return $iHeight EndFunc ;==>_CheckHeaderHeight ;============================================ Func _ScreenToClient($hWnd, ByRef $aCoord) Local $tPoint = DllStructCreate("int X;int Y") DllStructSetData($tPoint, "X", $aCoord[0]) DllStructSetData($tPoint, "Y", $aCoord[1]) DllCall("user32.dll", "bool", "ScreenToClient", "hwnd", $hWnd, "struct*", $tPoint) $aCoord[0] = $tPoint.X $aCoord[1] = $tPoint.Y EndFunc ;==>_ScreenToClient ;============================================== Func _resizeLVCols() ; resize listview columns to match header widths (1st display only, before any horizontal scrolling !) For $i = 0 To _GUICtrlHeader_GetItemCount($g_hHeader) - 1 _GUICtrlListView_SetColumnWidth($g_hListview, $i, _GUICtrlHeader_GetItemWidth($g_hHeader, $i)) Next ; In case column 0 got an icon, retrieve the width of the icon Local $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, $LVIR_ICON) ; bounding rectangle of the icon (if any) $g_iIconWidth = $aRectLV[2] - $aRectLV[0] ; without icon : 4 - 4 => 0 (tested, the famous "4" !) ; with icon of 20 pixels : 24 - 4 = 20 EndFunc ;==>_resizeLVCols ;============================================== Func _resizeLVCols2() ; called when the attributes of a header item have changed ($HDN_ITEMCHANGED) ; also called while the listview is scrolled horizontally or the Gui is being resized. Local $iCol, $aRectLV Local $aOrder = _GUICtrlHeader_GetOrderArray($g_hHeader) $iCol = $aOrder[1] ; left column (may not be column 0, if column 0 was dragged/dropped elsewhere) If $iCol > 0 Then ; LV subitem $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) Else ; column 0 needs _GUICtrlListView_GetItemRect() $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, $LVIR_LABEL) ; bounding rectangle of the item text $aRectLV[0] -= (4 + $g_iIconWidth) ; adjust LV col 0 left coord (+++) EndIf If $aRectLV[0] < 0 Then ; horizontal scrollbar is NOT at left => move and resize the detached header (mimic a normal listview) WinMove($g_hHeader, "", $aRectLV[0], 0, WinGetPos($g_hListview)[2] - $aRectLV[0], $g_iHeaderHeight) Else ; horizontal scrollbar is at left => move and resize the detached header to its initial coords & size WinMove($g_hHeader, "", 0, 0, WinGetPos($g_hListview)[2], $g_iHeaderHeight) EndIf EndFunc ;==>_resizeLVCols2 ;============================================== Func _reorderLVCols() ; remove LVS_NOCOLUMNHEADER from listview Local $i_Style_Old = _WinAPI_GetWindowLong($g_hListView, $GWL_STYLE) _WinAPI_SetWindowLong($g_hListView, $GWL_STYLE, BitXOR($i_Style_Old, $LVS_NOCOLUMNHEADER)) ; reorder listview columns order to match header items order Local $aOrder = _GUICtrlHeader_GetOrderArray($g_hHeader) _GUICtrlListView_SetColumnOrderArray($g_hListview, $aOrder) ; add LVS_NOCOLUMNHEADER back to listview _WinAPI_SetWindowLong($g_hListView, $GWL_STYLE, $i_Style_Old) EndFunc ;==>_reorderLVCols ;============================================== Func WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) ; called just before the gui resize starts. ; add $WS_EX_COMPOSITED to gui (reduce flicker while resizing) If $hWnd = $g_hGUI Then Local $i_Style_Old = _WinAPI_GetWindowLong($g_hGUI, $GWL_EXSTYLE) _WinAPI_SetWindowLong($g_hGUI, $GWL_EXSTYLE, BitOR($i_Style_Old, $WS_EX_COMPOSITED)) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_ENTERSIZEMOVE ;============================================== Func WM_EXITSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) ; called just after the gui resize ends. ; remove $WS_EX_COMPOSITED from gui If $hWnd = $g_hGUI Then Local $i_Style_Old = _WinAPI_GetWindowLong($g_hGUI, $GWL_EXSTYLE) _WinAPI_SetWindowLong($g_hGUI, $GWL_EXSTYLE, BitXOR($i_Style_Old, $WS_EX_COMPOSITED)) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_EXITSIZEMOVE ;============================================== Func WM_SIZE($hWnd, $iMsg, $wParam, $lParam) If $hWnd = $g_hGUI Then Local $iParentNewCliW = BitAND($lParam, 0xFFFF) ; low word Local $iParentNewCliH = BitShift($lParam, 16) ; high word WinMove($g_hChild, "", $iParentNewCliW * $g_nRatio[0], $iParentNewCliH * $g_nRatio[1], _ $iParentNewCliW * $g_nRatio[2], $iParentNewCliH * $g_nRatio[3]) ; WinMove will use Int coords Local $aPosLV = WinGetPos($g_hListView) Local $aCoord[2] = [$aPosLV[0], $aPosLV[1]] ; X, Y _ScreenToClient($g_hChild , $aCoord) ; $aCoord passed ByRef WinMove($g_hFrameHeader, "", $aCoord[0], $aCoord[1] - $g_iHeaderHeight, $aPosLV[2], $g_iHeaderHeight) _resizeLVCols2() EndIf EndFunc ;==>WM_SIZE ;============================================== Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) #forceref $hWnd, $iMsg, $wParam Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) Local $iCode = DllStructGetData($tNMHDR, "Code") Switch $hWndFrom Case $g_hHeader Switch $iCode Case $HDN_ITEMCHANGED, $HDN_ITEMCHANGEDW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item Local $tHDITEM = DllStructCreate($tagHDITEM, $tNMHEADER.pItem) Local $iHeaderItemWidth = $tHDITEM.XY _GUICtrlListView_SetColumnWidth($g_hListview, $iHeaderItem, $iHeaderItemWidth) _resizeLVCols2() Case $HDN_ENDDRAG GUICtrlSendToDummy($g_idDummyEndDrag) Return False ; to allow the control to automatically place and reorder the item Case $HDN_DIVIDERDBLCLICK, $HDN_DIVIDERDBLCLICKW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item _GUICtrlListView_SetColumnWidth($g_hListview, $iHeaderItem, $LVSCW_AUTOSIZE) _GUICtrlHeader_SetItemWidth($g_hHeader, $iHeaderItem, _GUICtrlListView_GetColumnWidth($g_hListview, $iHeaderItem)) _resizeLVCols2() Case $HDN_ITEMCLICK, $HDN_ITEMCLICKW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item _GUICtrlListView_SortItems($g_hListview, $iHeaderItem) EndSwitch Case $g_hListView Switch $iCode Case $LVN_ENDSCROLL Local Static $tagNMLVSCROLL = $tagNMHDR & ";int dx;int dy" Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $tNMLVSCROLL.dy = 0 Then ; ListView horizontal scrolling _resizeLVCols2() EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Edit: I'll probably create a 2nd script (nearly the same), but this time without a frame for the header, which will suit any script where the LV width equals exactly the child window width. Or maybe combine both in 1 script, testing this : * If Child window width = LV width : no frame for the detached header * If Child window width > LV width : add a frame to the detached header, to prevent its bad disp on the left side (no more above the LV) when the user scrolls to the right, as shown in the pic above. Thanks and have a great day Edit 2025-12-26 : updated code, thanks to @WildByDesign (you can read his advices in the posts below). Modifications were done to avoid flicker while moving a header divider. Edited Friday at 08:43 PM by pixelsearch Updated code (2025-12-26) WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Friday at 10:54 AM Author Posted Friday at 10:54 AM 2 hours ago, pixelsearch said: You would need HDN_ITEMCHANGING for example to prevent that an attribute of the item is about to change, by returning True and won't let it change. Placing a counter inside both Case (ITEMCHANGING and ITEMCHANGED) will show you that there are called dozen of times (and both the same number of times) when you move the divider a couple of millimeters. So HDN_ITEMCHANGED should be enough : I just checked and it worked very fine with only HDN_ITEMCHANGED. Good catch. I had assumed that HDN_ITEMCHANGING/W would be needed but I never did test with just HDN_ITEMCHANGED/W. So it's great that you pointed it out. It works, as you said, and it should also make it a bit more efficient. 2 hours ago, pixelsearch said: That was a challenge to me, because imagine what could happen if you choosed 50 instead of 10, then your LV would appear like this, as soon as you start to scroll a bit to the right : You probably already noticed this is happening in your script, the little gap on the left side of LV when you added 10 to x, no matter you indicated it 3 times in the script (once when defining the LV, 2 other times inside the function _resizeLVCols2) This is a problem, for sure. I personally have never seen that. The LVS_EX_DOUBLEBUFFER in the ListView control should prevent things like that from happening. But since it is happening for you then that means it could happen for other users as well and that is a problem. The main reason why I created the 10px margin on the LV was because the separator initially had a problem where it would highlight things on both sides (TreeView and ListView) when the separator was moving. But I solved that directly in the GUIFrame UDF with _WinAPI_SetCapture during movement of separator and _WinAPI_ReleaseCapture once the separator stops moving. That solved the problem nicely and made the separator move more smoothly as well. If it's better to get rid of the margin then I could use _GUICtrlListView_SetItemIndent to indent the ListView items. I'm pretty sure that is what File Explorer does in Windows 11 because the items are indented further in from where the header is. I have experimented with it before but I would have to call it from within the TreeListExplorer UDF since that is where the items are created. I'll take a look into that. 2 hours ago, pixelsearch said: Please be kind to test the script quickly and let me know if it flickers or not on your computer. I'd like to keep it as a canvas for the scripts to come, when a listview is used in a resizable GUI and the user would like to avoid flicker. It seems to flicker quite significantly, unfortunately. It doesn't flicker during GUI resize, but when you move any of the header dividers is flickers quite bad. The entire ListView flickers and the header item currently being resized also flickers. I tried a few things to prevent the flicker but did not help.
WildByDesign Posted Friday at 12:51 PM Author Posted Friday at 12:51 PM FilesAu3-2025-12-26: I've updated the release on the first post. 4 hours ago, pixelsearch said: That was a challenge to me, because imagine what could happen if you choosed 50 instead of 10, then your LV would appear like this, as soon as you start to scroll a bit to the right : You probably already noticed this is happening in your script, the little gap on the left side of LV when you added 10 to x, no matter you indicated it 3 times in the script (once when defining the LV, 2 other times inside the function _resizeLVCols2) Can you please test the new release and see if this is still an issue? I made sure that the detached header and ListView are both at 0 x and removed the + 10 x in any of the functions that moved them. I ended up creating a 5px space in the separator GUI on the right side to give more space to the ListView. I did end up experimenting with setting an indent to the ListView items with _GUICtrlListView_SetItemIndent but it ended up looking weird. It also could have been problematic when drag and drop reordering of columns. 4 hours ago, pixelsearch said: 2 things I changed in my version of _resizeLVCols2() 1) Deleted the following line, which created issues in the script I'll present below. The line was commented as "experimental"... If $iX_Old = $aRectLV[0] Then Return ; no need to move/resize the detached header in this case (experimental, to be confirmed) 2) Both WinMove($g_hHeader ...) use now WinGetPos(...)[2] instead of WinGetClientSize(...)[0] I made both of these changes and everything seems to work as expected.
pixelsearch Posted Friday at 02:22 PM Posted Friday at 02:22 PM 1 hour ago, WildByDesign said: Can you please test the new release and see if this is still an issue? I sure will do after posting this message. Now concerning my last script, you wrote : 3 hours ago, WildByDesign said: It doesn't flicker during GUI resize, but [...] Well that's already fantastic news, don't you think ? I mean, people always complain they got a flicker issue on the LV while they resize their GUI. As you reported that there was no flicker while resizing the GUI, it could mean that these 2 functions did the job, when using a LV + detached header : Func WM_ENTERSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) ; add $WS_EX_COMPOSITED to gui. If $hWnd = $g_hGUI Then Local $i_Style_Old = _WinAPI_GetWindowLong($g_hGUI, $GWL_EXSTYLE) _WinAPI_SetWindowLong($g_hGUI, $GWL_EXSTYLE, BitOR($i_Style_Old, $WS_EX_COMPOSITED)) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_ENTERSIZEMOVE Func WM_EXITSIZEMOVE($hWnd, $iMsg, $wParam, $lParam) ; remove $WS_EX_COMPOSITED from gui. If $hWnd = $g_hGUI Then Local $i_Style_Old = _WinAPI_GetWindowLong($g_hGUI, $GWL_EXSTYLE) _WinAPI_SetWindowLong($g_hGUI, $GWL_EXSTYLE, BitXOR($i_Style_Old, $WS_EX_COMPOSITED)) EndIf Return $GUI_RUNDEFMSG EndFunc ;==>WM_EXITSIZEMOVE Now concerning the remaining flicker while moving a divider. As I won't be able to test my script on a W11 computer before several weeks, could you please take 2 minutes to test this : 1) Please make sure you're using the original script from my preceding post. 2) Comment out these both parts : ; Case $HDN_BEGINTRACK, $HDN_BEGINTRACKW ; ... ; Case $HDN_ENDTRACK, $HDN_ENDTRACKW ; ... Is the problem solved or not, when moving a divider ? If it's not solved, then let's try your new solution : 3) Comment out also this part... ; Case $HDN_TRACK, $HDN_TRACKW ; ... ...then create the header as you indicated... ; $g_hHeader = _GUICtrlHeader_Create($g_hFrameHeader) $g_hHeader = _GUICtrlHeader_Create($g_hFrameHeader, BitOR($HDS_BUTTONS, $HDS_DRAGDROP, $HDS_FULLDRAG)) ...finally add the HDN_ITEMCHANGED part in its shortest way : Case $HDN_ITEMCHANGED, $HDN_ITEMCHANGEDW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item Local $tHDITEM = DllStructCreate($tagHDITEM, $tNMHEADER.pItem) Local $iHeaderItemWidth = $tHDITEM.XY _GUICtrlHeader_SetItemWidth($g_hHeader, $iHeaderItem, $iHeaderItemWidth) _GUICtrlListView_SetColumnWidth($g_hListview, $iHeaderItem, $iHeaderColWidth) _resizeLVCols2() Is it better now ? Let's hope things go better after these attempts, fingers double crossed. Thank you for testing "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Friday at 02:44 PM Author Posted Friday at 02:44 PM 18 minutes ago, pixelsearch said: 2) Comment out these both parts : ; Case $HDN_BEGINTRACK, $HDN_BEGINTRACKW ; ... ; Case $HDN_ENDTRACK, $HDN_ENDTRACKW ; ... Is the problem solved or not, when moving a divider ? If it's not solved, then let's try your new solution I’m not at my PC right now but I did test this. These were the cause of the divider movement flicker. Commenting these out made the divider movement smooth. 18 minutes ago, pixelsearch said: 3) Comment out also this part... I tested out switching to HDS_FULLDRAG also. It was also smooth. By the way, if you go with the FULLDRAG and HDN_ITEMCHANGED, you do not need to set the header width: _GUICtrlHeader_SetItemWidth($g_hHeader, $iHeaderItem, $iHeaderItemWidth) That can be removed because FULLDRAG is already setting the header item width while we move it with the mouse. That is the beauty of it. So you can do either method. But personally, I think FULLDRAG method looks nicer and is identical to the behavior that we see with standard ListView. pixelsearch 1
WildByDesign Posted Friday at 03:08 PM Author Posted Friday at 03:08 PM By the way, having WS_EX_COMPOSITED at the same time as the ListView having LVS_EX_DOUBLEBUFFER will cause some extra flickering. So whenever I add one, I remove the other. And vice versa. It only adds minor flicker though, not the major flicker that was happening. But the SetWindowLong never seemed to work for me with ListView extended styles. That is why I had to use _GUICtrlListView_SetExtendedListViewStyle and it works well. pixelsearch 1
pixelsearch Posted Friday at 03:25 PM Posted Friday at 03:25 PM (edited) 48 minutes ago, WildByDesign said: By the way, having WS_EX_COMPOSITED at the same time as the ListView having LVS_EX_DOUBLEBUFFER will cause some extra flickering. So whenever I add one, I remove the other. And vice versa. Interesting, thanks for the info. Your script from today 26 december : great with 0 pixels coord, issue solved when LV got no margin in child window. In fact it's easy to understand why : as the header stretches to the left when we scroll to the right, the header can't display anything on the left side (it would be outside the child window left side). When we leave space to the left, 1 pixel, 10, 50 then the header fills this margin as much as it can until it reaches the left side of the child window. That's why I created an additional frame to contain the header, in case the user doesn't want at all to have its LV width = child Width. But now yours work fine, no more issue when 0 pixel added to x, problem solved. 1 hour ago, WildByDesign said: By the way, if you go with the FULLDRAG and HDN_ITEMCHANGED, you do not need to set the header width: _GUICtrlHeader_SetItemWidth($g_hHeader, $iHeaderItem, $iHeaderItemWidth) That's right. Before reading your last posts, I was testing it after having a look at your last script, where you gladly got rid of the $tRECT lines in Case $HDN_ITEMCHANGED. The test I did was : ... Local $iHeaderItemWidth = $tHDITEM.XY ConsoleWrite($tHDITEM.XY & " " & _GUICtrlHeader_GetItemWidth($g_hHeader, $iHeaderItem) & @crlf) ... This same test in Case $HDN_TRACK and Case $HDN_ITEMCHANGED show what you indicated : the values are the same when $HDN_ITEMCHANGED is used (so we don't need the _GUICtrlHeader_SetItemWidth line) but the values are very different during Case $HDN_TRACK (where the _GUICtrlHeader_SetItemWidth line is mandatory) One issue I got with your script is this : if you got a horizontal scrollbar in your LV and it this scrollbar is NOT positioned to the very left, what happens when you change path in the tree folder ? On my computer the content of the new path in LV is not aligned with the headers, until you scroll by yourself, or move a divider etc... Does it happen by your side too ? Thanks for having tested my script, I'm very happy with its result. I'll amend the code above to reflect the definite changes, using $HDS_FULLDRAG style and $HDN_ITEMCHANGED notification etc... Then (maybe) I'll go a bit further and try to get rid of the additional header frame if the user indicates a LV width = child width, we'll see... Edit : now that this line has been deleted in _resizeLVCols2() ... If $iX_Old = $aRectLV[0] Then Return ; no need to move/resize the detached header in this case (experimental, to be confirmed) ...then we won't need these 2 lines, which should be deleted too : Local Static $iX_Old = 99999 ... $iX_Old = $aRectLV[0] Also, what should be done with this line ? ; WinSetState(_GUICtrlListView_GetHeader($idListview), "", @SW_DISABLE) ; <============================ useful ? The native header is always there. It's not because we create the LV with a $LVS_NOCOLUMNHEADER style that the native header is not created. It is created, its width = LV width, but its height = 0 because of $LVS_NOCOLUMNHEADER . It is enabled (thanks to free Nirsoft utilities for showing all this) . I got no idea if it should be disabled or not, as we're gonna use a detached header. For now, I didn't find differences when enabled or disabled. Edited Friday at 03:55 PM by pixelsearch added comments WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Saturday at 12:30 AM Author Posted Saturday at 12:30 AM (edited) 9 hours ago, pixelsearch said: But now yours work fine, no more issue when 0 pixel added to x, problem solved. Thanks for confirming. I appreciate you helping to test it as well. 9 hours ago, pixelsearch said: One issue I got with your script is this : if you got a horizontal scrollbar in your LV and it this scrollbar is NOT positioned to the very left, what happens when you change path in the tree folder ? On my computer the content of the new path in LV is not aligned with the headers, until you scroll by yourself, or move a divider etc... Does it happen by your side too ? Good catch. You're right, that is a problem. I decided to check a few other file manager programs to see how they behave in this situation. When they have the columns wide enough that the horizontal scrollbar is visible and the scrollbar is not at the left side, they seem to move the scrollbar to the left side when navigating to another directory. Columns stay the same size but scrollbar moves to the left. I've done this in the 2025-12-26-r1 release on the first post. If you have a moment, could you please test it to see if it resolves the issue that you mentioned? I probably could use your help to improve it. In the main While loop, it is located in the following: If $bPathInputChanged Then ; reset position of header and listview _addExStyles() For $i = 1 To 1000 GUICtrlSendMsg($idListview, $WM_HSCROLL, $SB_LINELEFT, 0) Next WinMove($g_hHeader, "", 0, 0, WinGetPos($g_hChild)[2], Default) It works quite well in my testing. But it certainly could be improved. I put To 1000, but the amount that the scrollbar would likely be much less than that. It could technically be more than that as well. Somehow we need to get the position of the scrollbar from the left side. 9 hours ago, pixelsearch said: Also, what should be done with this line ? ; WinSetState(_GUICtrlListView_GetHeader($idListview), "", @SW_DISABLE) ; <============================ useful ? The native header is always there. It's not because we create the LV with a $LVS_NOCOLUMNHEADER style that the native header is not created. It is created, its width = LV width, but its height = 0 because of $LVS_NOCOLUMNHEADER . It is enabled (thanks to free Nirsoft utilities for showing all this) . I got no idea if it should be disabled or not, as we're gonna use a detached header. For now, I didn't find differences when enabled or disabled. I would just delete that line and I don't think that we need to mess around with it. I used System Informer a few days ago to try enabling/disabling it, toggling visibility and also destroying/closing the handle for it. It seems that even with $LVS_NOCOLUMNHEADER, it still needs its built-in header. Somehow it still relies on it. Edited Saturday at 12:32 AM by WildByDesign
pixelsearch Posted Saturday at 03:15 AM Posted Saturday at 03:15 AM 2 hours ago, WildByDesign said: I've done this in the 2025-12-26-r1 release on the first post. If you have a moment, could you please test it to see if it resolves the issue that you mentioned? I probably could use your help to improve it. In the main While loop, it is located in the following: If $bPathInputChanged Then ; reset position of header and listview _addExStyles() For $i = 1 To 1000 GUICtrlSendMsg($idListview, $WM_HSCROLL, $SB_LINELEFT, 0) Next WinMove($g_hHeader, "", 0, 0, WinGetPos($g_hChild)[2], Default) Yes it's solved now, but you don't need to loop 1000 times, unit by unit, using SB_LINELEFT . Sending the message only once, like the following, would move the thumb to its very left position : GUICtrlSendMsg($idListview, $WM_HSCROLL, $SB_LEFT, 0) Unfortunately, $SB_LEFT is missing in AutoIt (also $SB_RIGHT and $SB_ENDSCROLL if not mistaken). Their values can be retrieved in WinUser.h SB_LEFT (6) same value as $SB_TOP used in vertical scrolling. SB_RIGHT (7) same value as SB_BOTTOM used in vertical scrolling. SB_ENDSCROLL (8) But there is something more : you don't need the message at all in your script, because as soon as you change path, then the scrollbar is placed automatically at its very left position (I already noticed this behavior and you can try it with any of your older versions, like the one from the 26 december, not the -r1, or the release from Dec 25) What you just need to solve the issue is the line that moves the header to its initial position, as found in your last release : WinMove($g_hHeader, "", 0, 0, WinGetPos($g_hChild)[2], Default) For the record, even if $SB_LEFT didn't exist and you needed to scroll to the very left, this would have done it : _GUICtrlListView_Scroll($idListview, -10000000000, 0) ; scroll 10000000000 pixels to the left You can try all this (as I just did) with the help file example, topic _GUICtrlListView_Scroll, after making sure there is a visible horizontal scrollbar : ; Add column ; _GUICtrlListView_AddColumn($idListview, "Items", 100) _GUICtrlListView_AddColumn($idListview, "Items", 1000) ; larger than GUI width Good luck WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted Saturday at 10:55 AM Author Posted Saturday at 10:55 AM 7 hours ago, pixelsearch said: But there is something more : you don't need the message at all in your script, because as soon as you change path, then the scrollbar is placed automatically at its very left position (I already noticed this behavior and you can try it with any of your older versions, like the one from the 26 december, not the -r1, or the release from Dec 25) I'm not sure why, but in the previous releases on my Win11 machine, the scrollbar would not automatically get placed back at its very left position. I did see the misalignment that you mentioned though for the header/listview. Thanks for all of those possible ideas for moving the position of the scrollbar. It's pretty neat having several options. I ended up going with the following: Global Const $SB_LEFT = 6 ... If $bPathInputChanged Then ; reset position of header and listview GUICtrlSendMsg($idListview, $WM_HSCROLL, $SB_LEFT, 0) WinMove($g_hHeader, "", 0, 0, WinGetPos($g_hChild)[2], Default) Since my scrollbar wasn't automatically going back to the left position, I had to add that one line in there still but it all seems to work great now like that.
WildByDesign Posted 18 hours ago Author Posted 18 hours ago (edited) I've added full support for Windows 11 materials (Mica, Acrylic, Tabbed, etc.) for all controls except the header. I'm not quite sure how to do the header yet. I'm not quite ready to upload the source changes yet. But I'm adding a screenshot although I've never used ImgBB before so not sure yet if it will show. The screenshot is with Acrylic just for show. I personally don't like Acrylic and prefer Mica or Tabbed. Edited 18 hours ago by WildByDesign
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