WildByDesign Posted December 6 Author Posted December 6 (edited) @pixelsearch I have a question regarding the following code: Case $LVN_ENDSCROLL Local Static $tagNMLVSCROLL = $tagNMHDR & ";int dx;int dy" Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $tNMLVSCROLL.dy = 0 Then ; ListView horizontal scrolling _resizeHeaderItems() EndIf The horizontal scrolling is very smooth. However, I notice occasionally that vertical scrolling can cause some flicker. Now, there is no need to resize headers when vertical scrolling, of course. However, if we can run _changeExStyles() when vertical scrolling is detected, I am pretty confident that it will get rid of any vertical scrolling flicker. Is there a way to run that function when vertical scrolling is detected? Thank you. EDIT: I ended up figuring it out thanks to you already having the structure in place. Thanks again. Case $LVN_ENDSCROLL Local Static $tagNMLVSCROLL = $tagNMHDR & ";int dx;int dy" Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $tNMLVSCROLL.dy = 0 Then ; ListView horizontal scrolling _resizeHeaderItems() EndIf If $tNMLVSCROLL.dx = 0 Then ; ListView vertical scrolling ConsoleWrite("vertical scrolling detected" & @CRLF) EndIf Edited December 6 by WildByDesign
pixelsearch Posted December 6 Posted December 6 (edited) 1 hour ago, WildByDesign said: I ended up figuring it out thanks to you already having the structure in place. Thanks again. Yes but please be careful, $LVN_ENDSCROLL shouldn't be the right place to run _changeExStyles() , I would place it when $LVN_BEGINSCROLL is detected (for vertical scrolling only) Here is a WM_NOTIFY function (just for test purpose) . It indicates how many times each notification occurs. From all notifications found in the function, only 4 are triggered a lot of times (when others are triggered only once. These 4 frequent notifications are : $HDN_TRACK, $HDN_TRACKW, $LVN_BEGINSCROLL, $LVN_ENDSCROLL As you suggested, I added _changeExStyles() in the $LVN_BEGINSCROLL part (when vertical scroll begins). As $LVN_BEGINSCROLL / $LVN_ENDSCROLL are constantly triggered when the scrollbars are moved, you'll have to check on your computer if calling _changeExStyles() so frequently creates an issue... or not. Good luck expandcollapse popupFunc 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_TRACK, $HDN_TRACKW Local Static $iHDN_TRACK = 0 $iHDN_TRACK += 1 ConsoleWrite("$iHDN_TRACK #" & $iHDN_TRACK & @crlf) 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) _resizeLVCols() ; <======================== Return False ; to continue tracking the divider Case $HDN_BEGINTRACK, $HDN_BEGINTRACKW Local Static $iHDN_BEGINTRACK = 0 $iHDN_BEGINTRACK += 1 ConsoleWrite("$iHDN_BEGINTRACK #" & $iHDN_BEGINTRACK & @crlf) Return False ; To allow tracking of the divider Case $HDN_ENDTRACK, $HDN_ENDTRACKW Local Static $iHDN_ENDTRACK = 0 $iHDN_ENDTRACK += 1 ConsoleWrite("$iHDN_ENDTRACK #" & $iHDN_ENDTRACK & @crlf) Case $HDN_BEGINDRAG Local Static $iHDN_BEGINDRAG = 0 $iHDN_BEGINDRAG += 1 ConsoleWrite("$iHDN_BEGINDRAG #" & $iHDN_BEGINDRAG &@crlf) Return False ; To allow the header control to automatically manage drag-and-drop operations Case $HDN_ENDDRAG Local Static $iHDN_ENDDRAG = 0 $iHDN_ENDDRAG += 1 ConsoleWrite("$iHDN_ENDDRAG #" & $iHDN_ENDDRAG & @crlf) $g_bHeaderEndDrag = True ; <======================== Return False ; to allow the control to automatically place and reorder the item Case $HDN_ITEMCLICK, $HDN_ITEMCLICKW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item ConsoleWrite("Item " & $iHeaderItem & " clicked" & @crlf) Case $HDN_DIVIDERDBLCLICK, $HDN_DIVIDERDBLCLICKW Local $tNMHEADER = DllStructCreate($tagNMHEADER, $lParam) Local $iHeaderItem = $tNMHEADER.Item ConsoleWrite("Divider " & $iHeaderItem & " double clicked" & @crlf) EndSwitch Case $g_hListView Switch $iCode Case $LVN_BEGINSCROLL, $LVN_ENDSCROLL Local Static $iLVN_BEGINSCROLL_H = 0, $iLVN_ENDSCROLL_H = 0, $iLVN_BEGINSCROLL_V = 0, $iLVN_ENDSCROLL_V = 0 Local Static $tagNMLVSCROLL = $tagNMHDR & ";int dx;int dy" Local $tNMLVSCROLL = DllStructCreate($tagNMLVSCROLL, $lParam) If $tNMLVSCROLL.dy = 0 Then ; ListView horizontal scrolling Switch $iCode Case $LVN_BEGINSCROLL $iLVN_BEGINSCROLL_H += 1 ConsoleWrite("$iLVN_BEGINSCROLL_H #" & $iLVN_BEGINSCROLL_H & @crlf) Case Else ; $LVN_ENDSCROLL $iLVN_ENDSCROLL_H += 1 ConsoleWrite("$iLVN_ENDSCROLL_H #" & $iLVN_ENDSCROLL_H & @crlf) _resizeHeaderItems() ; <======================== EndSwitch Else ; ListView vertical scrolling Switch $iCode Case $LVN_BEGINSCROLL $iLVN_BEGINSCROLL_V += 1 ConsoleWrite("$iLVN_BEGINSCROLL_V #" & $iLVN_BEGINSCROLL_V & @crlf) _changeExStyles() ; <======================== Case Else ; $LVN_ENDSCROLL $iLVN_ENDSCROLL_V += 1 ConsoleWrite("$iLVN_ENDSCROLL_V #" & $iLVN_ENDSCROLL_V & @crlf) EndSwitch EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Edited December 6 by pixelsearch typo WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 6 Author Posted December 6 (edited) 22 minutes ago, pixelsearch said: you'll have to check on your computer if calling _changeExStyles() so frequently creates an issue... or not Realistically, I should figure out a way to limit how often it gets called. I have to find a way to track that and keep a variable of the time difference. Since the Adlib stays active for 3 seconds before reverting styles, the _changeExStyles() technically only needs to be called every 2 seconds maybe. I actually tried to track this time diff earlier but failed miserably. I’ll have to try again though because it would be important for performance and efficiency. Edited December 6 by WildByDesign
pixelsearch Posted December 6 Posted December 6 For the record, calling _changeExStyles() from $LVN_BEGINSCROLL behaves badly on my computer (vertical scrolling down and up, which calls _changeExStyles() dozen of times in a few ms, when the function adds/removes styles to the GUI/LV with a timer each 3s . This is the wrong display I got now : 11 minutes ago, WildByDesign said: I’ll have to try again though because it would be important for performance and efficiency. Hope you'll find a way. Good luck WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 7 Author Posted December 7 19 hours ago, pixelsearch said: For the record, calling _changeExStyles() from $LVN_BEGINSCROLL behaves badly on my computer (vertical scrolling down and up, which calls _changeExStyles() dozen of times in a few ms, when the function adds/removes styles to the GUI/LV with a timer each 3s . This is the wrong display I got now : I just wanted to confirm that I get those glitches with $LVN_BEGINSCROLL as well. It seems to be guaranteed to be problematic. For whatever reason, I don't know, but having it in $LVN_ENDSCROLL seems to work 100% for me. No issues there. 19 hours ago, pixelsearch said: Hope you'll find a way. Good luck I had been trying many overly complicated methods which failed. I ended up going with a high precision timer which was more simplistic but works very well. Initially I had the timer for 3 seconds to match the adlib but it would cause an occasional flicker in between. So I switched the timer to 2 seconds while the adlib is at 3 seconds to allow some overlap. In this case, the function does a Return immediately if it was already called less than 2 seconds prior. If it's between 2-3 seconds, it will call it again and also reset the 3 second adlib timer. So while that all works well and efficiently, I'm trying some other ideas at the moment.
WildByDesign Posted December 7 Author Posted December 7 On 12/5/2025 at 9:55 PM, ioa747 said: and, after a little observation, I noticed that after each change of _GUIFrame, it updates the GUI with Msg 4, so By the way, how did you find out the possible Msg numbers? Do you know if there is a Msg related to starting the movement of the separator? As opposed to after it has moved?
ioa747 Posted December 7 Posted December 7 2 hours ago, WildByDesign said: By the way, how did you find out the possible Msg numbers? as I said, after a little observation after reading the index ; #CURRENT# ========================================================================================================== ; _GUIFrame_Create: Splits a GUI into 2 frames ; _GUIFrame_SetMin: Sets minimum sizes for each frame ; _GUIFrame_ResizeSet: Sets resizing flag for all or specified frame sets ; _GUIFrame_GetHandle: Returns the handle of a frame element (required for further splitting) ; _GUIFrame_Switch: Sets a frame element as current GUI ; _GUIFrame_GetSepPos: Returns the current position of the separator ; _GUIFrame_SetSepPos: Moves the separator bar to adjust frame sizes ; _GUIFrame_ResizeState: Returns the resize state of the frames ; _GUIFrame_ResizeReg: Registers WM_SIZE message for resizing ; _GUIFrame_SIZE_Handler: WM_SIZE message handler to resize frames using _GUIFrame_Move ; ==================================================================================================================== ; #INTERNAL_USE_ONLY#================================================================================================= ; _GUIFrame_SepSubClass: Sets new WndProc for frame separator bar ; _GUIFrame_SepWndProc: New WndProc for frame separator bar ; _GUIFrame_SepPassMsg: Passes Msg to original frame WndProc for action ; _GUIFrame_Move: Moves and resizes frame elements and separator bars ; _GUIFrame_Exit: Deletes all subclassed separator bars to free UDF WndProc and frees registered callback handle ; ==================================================================================================================== I noticed the _GUIFrame_SepPassMsg: Passes Msg to original frame WndProc for action and then I put it While True Local $iMsg = GUIGetMsg() Switch $iMsg ... Case Else If $iMsg <> 0 Then ConsoleWrite("$iMsg=" & $iMsg & @CRLF) EndSwitch WEnd to see WildByDesign 1 I know that I know nothing
WildByDesign Posted December 8 Author Posted December 8 Is there a way to trigger a GUI Msg that can be picked up in the GUIGetMsg() While loop? For example, in the GUIFrame UDF file in function _GUIFrame_SepWndProc(), there is a section of code that gets triggered anytime you move the separator. Here: ; Move the GUIs to the correct places WinMove($hFirstFrame, "", 0, 0, $iFirstWidth, $iHeight) WinMove($hSecondFrame, "", $iFirstWidth + $iSeparatorSize, 0, $iWidth - ($iFirstWidth + $iSeparatorSize), $iHeight) WinMove($hSeparator, "", $iFirstWidth, 0, $iSeparatorSize, $iHeight) And also in the ElseIf below it: WinMove($hFirstFrame, "", 0, 0, $iWidth, $iFirstHeight) WinMove($hSecondFrame, "", 0, $iFirstHeight + $iSeparatorSize, $iWidth, $iHeight - ($iFirstHeight + $iSeparatorSize)) WinMove($hSeparator, "", 0, $iFirstHeight, $iWidth, $iSeparatorSize) If there is a way to put something there that would trigger a specific GUI Msg, then I can do some interesting things with it. That is the only area that seems to trigger while the separator is actually moving instead of after it stops moving.
WildByDesign Posted December 9 Author Posted December 9 @pixelsearch After a few days, I ended up finding a far more efficient way to do it for the GUIFrame stuff. I made it so that the extended styles are only modified (briefly) when the GUIFrame separator is moving. I realized that that is technically the only time in which we really need WS_EX_COMPOSITED. This way it's not getting constantly hammered with all of the ListView and header activity. Plus, I still have it limited to every 750ms. Anyway, as a result of everyone's help here, I have finally opened up the project collab thread for Files Au3 - AutoIt File Manager @ioa747 I've got the header resizing in real-time now while the separator is moving which is nice. I had to modify the UDF to do it for now, but if you have a proper way to do it please let me know. ioa747 1
pixelsearch Posted December 9 Posted December 9 (edited) Here is an improved version concerning the horizontal scrolling / header resizing / cols reordering, when a "detached" header control needs to be "linked" to a listview that has no headers. Also a button "Infos" has been added, it allows to display anytime in the console informations concerning the actual position & rectangle size of all headers & columns. Some code should probably be improved, but that's all I got for now. Hope it helps expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiListView.au3> #include <StructureConstants.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> ; DPI ; DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGUI, $g_hChild, $g_hHeader, $g_hListview, $g_bHeaderEndDrag Example() Func Example() $g_hGUI = GUICreate("Example", 400, 400, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_TOPMOST) GUISetBkColor(0x202020) Local $idButton = GUICtrlCreateButton("Infos", 160, 370, 80, 20) GUISetState(@SW_SHOW, $g_hGUI) $g_hChild = GUICreate("ChildWindow", 320, 320, 40, 40, $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0x606060) $g_hHeader = _GUICtrlHeader_Create($g_hChild) Local $iHeaderHeight = _WinAPI_GetWindowHeight($g_hHeader) For $i = 0 To 3 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 120) Next Local $idListview = GUICtrlCreateListView("col0|col1|col2|col3", 0, $iHeaderHeight, 320, 320 - $iHeaderHeight, _ BitOR($GUI_SS_DEFAULT_LISTVIEW, $LVS_NOCOLUMNHEADER), $LVS_EX_FULLROWSELECT) $g_hListview = GUICtrlGetHandle($idListview) _GUICtrlListView_BeginUpdate($idListview) For $i = 1 To 30 GUICtrlCreateListViewItem("item" & $i & "-0|item" & $i & "-1|item" & $i & "-2|item" & $i & "-3", $idListview) Next _GUICtrlListView_EndUpdate($idListview) ; resize listview columns to match header widths _resizeLVCols() GUISetState(@SW_SHOW, $g_hChild) ; get rid of dotted rectangle in listview, when an item got the focus GUICtrlSendMsg($idListview, $WM_CHANGEUISTATE, 65537, 0) GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idButton GUICtrlSetState($idButton, $GUI_DISABLE) _Infos() GUICtrlSetState($idButton, $GUI_ENABLE) EndSwitch If $g_bHeaderEndDrag Then $g_bHeaderEndDrag = False _reorderLVCols() EndIf WEnd _GUICtrlHeader_Destroy($g_hHeader) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example ;============================================== Func _Infos() Local $iCol, $iHDColWidth, $iLVColWidth, $aRectHD, $aRectLV Local $aOrder = _GUICtrlHeader_GetOrderArray($g_hHeader) Local Static $iTest = 0 $iTest +=1 ConsoleWrite("#" & $iTest & @TAB & "Column" & @TAB & "Left" & @TAB & "Right" & @TAB & "Width" & @crlf) For $iIndex = 1 To $aOrder[0] $iCol = $aOrder[$iIndex] $aRectHD = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) ; remember $aRectHD[0] & $aRectHD[2] always >= 0 in a Header rectangle If $iCol > 0 Then ; LV subitem $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) ; $aRect[0] & $aRect[2] may be < 0 in a ListView rectangle Else ; LV item (col 0) and its annoying rectangle size $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, 2) ; 2 = bounding rectangle of the item text $aRectLV[0] -= 4 ; adjust LV col 0 left coord (+++) EndIf $iHDColWidth = _GUICtrlHeader_GetItemWidth($g_hHeader, $iCol) $iLVColWidth = _GUICtrlListView_GetColumnWidth($g_hListView, $iCol) ConsoleWrite("+Header" & @TAB & $iCol & @TAB & $aRectHD[0] & @TAB & $aRectHD[2] & @TAB & $iHDColWidth & @crlf) ConsoleWrite("-ListV" & @TAB & $iCol & @TAB & $aRectLV[0] & @TAB & $aRectLV[2] & @TAB & $iLVColWidth & @crlf) Next ConsoleWrite(@crlf) EndFunc ;==>Infos ;============================================== Func _resizeHeaderItems() ; after each horizontal scroll notification (function seems to work fine) Local $aRectLV For $iCol = 0 To _GUICtrlListView_GetColumnCount($g_hListView) - 1 If $iCol Then $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) ; $aRect[0] & $aRect[2] may be < 0 in a ListView rectangle Else ; column 0 needs _GUICtrlListView_GetItemRect() in case it has been dragged elsewhere $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, $iCol, 2) ; 2 = bounding rectangle of the item text $aRectLV[0] -= 4 ; adjust LV col 0 left coord (+++) EndIf _GUICtrlHeader_SetItemWidth( $g_hHeader, $iCol, $aRectLV[2] - (($aRectLV[0] > 0) ? $aRectLV[0] : 0) ) Next EndFunc ;==>_resizeHeaderItems ;============================================== 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 EndFunc ;==>_resizeLVCols ;============================================== Func _resizeLVCols2() ; called while a header item is tracked (to be improved) . Also called from _reorderLVCols() Local $aRectHD, $aRectLV For $iCol = 0 To _GUICtrlListView_GetColumnCount($g_hListView) - 1 $aRectHD = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) ; remember $aRectHD[0] & $aRectHD[2] always >= 0 in a Header rectangle If $iCol Then $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) ; $aRect[0] & $aRect[2] may be < 0 in a ListView rectangle Else ; column 0 needs _GUICtrlListView_GetItemRect() in case it has been dragged elsewhere $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, 2) ; 2 = bounding rectangle of the item text $aRectLV[0] -= 4 ; adjust LV col 0 left coord (+++) EndIf If $aRectLV[0] < 0 And $aRectHD[2] > 0 Then $aRectHD[0] = $aRectLV[0] _GUICtrlListView_SetColumnWidth($g_hListview, $iCol, $aRectHD[2] - $aRectHD[0]) Next EndFunc ;==>_resizeLVCols2 ;============================================== Func _reorderLVCols() ; remove LVS_NOCOLUMNHEADER from listview __WinAPI_Set_Window_Style($g_hListView, $LVS_NOCOLUMNHEADER, False, False) ; 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_Set_Window_Style($g_hListView, $LVS_NOCOLUMNHEADER, True, False) _resizeLVCols2() EndFunc ;==>_reorderLVCols ;============================================== Func __WinAPI_Set_Window_Style($hWnd, $i_Style, $b_Add, $b_exStyle = False) ; compacted code (from Kafu's original) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $iIndex = $b_exStyle ? $GWL_EXSTYLE : $GWL_STYLE ; $iIndex as named by msdn & help file Local $i_Style_Old = _WinAPI_GetWindowLong($hWnd, $iIndex) If $b_Add Then If BitAND($i_Style_Old, $i_Style) Then Return ; style already applied _WinAPI_SetWindowLong($hWnd, $iIndex, BitOR($i_Style_Old, $i_Style)) Else ; remove If Not BitAND($i_Style_Old, $i_Style) Then Return ; style not set _WinAPI_SetWindowLong($hWnd, $iIndex, BitXOR($i_Style_Old, $i_Style)) EndIf Local $iRet = _WinAPI_SetWindowPos($hWnd, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_FRAMECHANGED, $SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER)) ; +++ If Not $iRet Then MsgBox($MB_TOPMOST, "_WinAPI_SetWindowPos", "Error = " & _WinAPI_GetLastError() & " Message = " & _WinAPI_GetLastErrorMessage()) EndFunc ;==>__WinAPI_Set_Window_Style ;============================================== 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_TRACK, $HDN_TRACKW 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) _resizeLVCols2() Return False ; to continue tracking the divider Case $HDN_ENDDRAG $g_bHeaderEndDrag = True Return False ; to allow the control to automatically place and reorder the item 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 _resizeHeaderItems() EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY Edited December 9 by pixelsearch typo WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 9 Author Posted December 9 (edited) 25 minutes ago, pixelsearch said: Here is an improved version concerning the horizontal scrolling / header resizing / cols reordering, when a "detached" header control needs to be "linked" to a listview that has no headers. I really appreciate your help with this, thank you. In your examples, your original _resizeLVCols() and newer _resizeLVCols2() both work perfectly, 100% of the time. For some reason, both of them seem to always be off by about 20 pixels in Files Au3. And it's always consistently around 20 pixels. 25 minutes ago, pixelsearch said: Also a button "Infos" has been added, it allows to display anytime in the console informations concerning the actual position & rectangle size of all headers & columns This is really quite helpful. I decided to bring your _Infos() into Files Au3 so that I could call it anytime with a hotkey. Here are some examples of what I am getting in the output with dragging of header: +Header 2 0 150 150 -ListV 2 0 150 150 +Header 0 150 566 416 -ListV 0 170 590 440 +Header 1 566 666 100 -ListV 1 590 690 100 Here is an example of before horizontal scroll: +Header 0 0 506 506 -ListV 0 20 506 506 +Header 1 506 606 100 -ListV 1 506 606 100 +Header 2 606 756 150 -ListV 2 606 756 150 And here is after horizontal scroll (bringing scrollbar to the right and back to the left) +Header 0 0 482 482 -ListV 0 20 506 506 +Header 1 482 582 100 -ListV 1 506 606 100 +Header 2 582 732 150 -ListV 2 606 756 150 I am just not 100% sure what it is about Files Au3 that makes the _resizeLVCols() and _resizeLVCols2() functions end up having some of the columns off by approx. 20 or so pixels. I just don't quite understand it. Edited December 9 by WildByDesign
pixelsearch Posted December 9 Posted December 9 (edited) 2 hours ago, WildByDesign said: In your examples, your original _resizeLVCols() and newer _resizeLVCols2() both work perfectly, 100% of the time. Delighted to hear that, as would say our dear friend @Melba23 As you got icons in your ListView (left column), then you'll probably have to work on this : Run your amended script 4 times, changing each time a value in the function Infos() , inside this line : GUICtrlListView_GetItemRect(... , ... , $iPart) Retrieve immediate Infos() by pressing your hotkey : don't press or scroll anything else before ! $iPart = $LVIR_BOUNDS (0) #1 Column Left Right Width +Header 0 0 300 300 -ListV 0 -4 550 300 $iPart = $LVIR_ICON (1) #1 Column Left Right Width +Header 0 0 300 300 -ListV 0 0 20 300 <==== here appears your "20", it is the icon width $iPart = $LVIR_LABEL (2) #1 Column Left Right Width +Header 0 0 300 300 -ListV 0 16 300 300 <==== Right - Left gives the most approaching LV col width 300... (*) $iPart = LVIR_SELECTBOUNDS (3) #1 Column Left Right Width +Header 0 0 300 300 -ListV 0 -4 550 300 (*) ...having in mind the icon width (20) and the line $aRectLV[0] -= 4 Good luck Edit: please don't forget this line is found 3 times in the script, in case you intend to test different values in it : $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, 2) ; 2 = bounding rectangle of the item text Edited December 9 by pixelsearch added the edit comment ioa747 and WildByDesign 2 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 9 Author Posted December 9 4 hours ago, pixelsearch said: As you got icons in your ListView (left column), then you'll probably have to work on this I can’t believe I didn’t think about the icons. The funny thing is that I know that the standard icon size is 20px on my 125% scaled monitor. The good thing is that I already have a variable in the Files Au3 script that stores the icon size which already takes into account the DPI scaling.
pixelsearch Posted December 10 Posted December 10 I just tried this revised code, in case an icon is found in column 0 . Let's hope it will solve your alignment issue. expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiImageList.au3> #include <GuiListView.au3> #include <StructureConstants.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> ; DPI ; DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -2) Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration Global $g_hGUI, $g_hChild, $g_hHeader, $g_hListview, $g_iIconWidth, $g_bHeaderEndDrag Example() Func Example() $g_hGUI = GUICreate("Example", 400, 400, -1, -1, $WS_OVERLAPPEDWINDOW, $WS_EX_TOPMOST) GUISetBkColor(0x202020) Local $idButton = GUICtrlCreateButton("Infos", 160, 370, 80, 20) $g_hChild = GUICreate("ChildWindow", 320, 320, 40, 40, $WS_CHILD, -1, $g_hGUI) GUISetBkColor(0x606060) $g_hHeader = _GUICtrlHeader_Create($g_hChild) Local $iHeaderHeight = _WinAPI_GetWindowHeight($g_hHeader) For $i = 0 To 3 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 120) Next Local $idListview = GUICtrlCreateListView("col0|col1|col2|col3", 0, $iHeaderHeight, 320, 320 - $iHeaderHeight, _ BitOR($GUI_SS_DEFAULT_LISTVIEW, $LVS_NOCOLUMNHEADER), $LVS_EX_FULLROWSELECT) $g_hListview = GUICtrlGetHandle($idListview) 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 29 _GUIImageList_AddIcon($hImageList, @SystemDir & "\shell32.dll", $i + 204) Next _GUICtrlListView_SetImageList($idListview, $hImageList, 1) ; 1 = image list with small icons _GUICtrlListView_BeginUpdate($idListview) For $i = 0 To 29 _GUICtrlListView_AddItem($idListview, "item" & $i & "-0", $i) For $j = 1 To 3 _GUICtrlListView_AddSubItem($idListview, $i, "item" & $i & "-" & $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) ; get rid of dotted rectangle in listview, when an item got the focus GUICtrlSendMsg($idListview, $WM_CHANGEUISTATE, 65537, 0) GUIRegisterMsg($WM_NOTIFY, WM_NOTIFY) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idButton GUICtrlSetState($idButton, $GUI_DISABLE) _Infos() GUICtrlSetState($idButton, $GUI_ENABLE) EndSwitch If $g_bHeaderEndDrag Then $g_bHeaderEndDrag = False _reorderLVCols() EndIf WEnd _GUIImageList_Destroy($hImageList) ; needed ? _GUICtrlHeader_Destroy($g_hHeader) GUIDelete($g_hChild) GUIDelete($g_hGUI) EndFunc ;==>Example ;============================================== Func _Infos() Local $iCol, $iHDColWidth, $iLVColWidth, $aRectHD, $aRectLV Local $aOrder = _GUICtrlHeader_GetOrderArray($g_hHeader) Local Static $iTest = 0 $iTest +=1 ConsoleWrite("#" & $iTest & @TAB & "Column" & @TAB & "Left" & @TAB & "Right" & @TAB & "Width" & @crlf) For $iIndex = 1 To $aOrder[0] $iCol = $aOrder[$iIndex] $aRectHD = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) ; remember $aRectHD[0] & $aRectHD[2] always >= 0 in a Header rectangle If $iCol > 0 Then ; LV subitem $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) ; $aRectLV[0] & $aRectLV[2] may be < 0 in a ListView rectangle 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 $iHDColWidth = _GUICtrlHeader_GetItemWidth($g_hHeader, $iCol) $iLVColWidth = _GUICtrlListView_GetColumnWidth($g_hListView, $iCol) ConsoleWrite("+Header" & @TAB & $iCol & @TAB & $aRectHD[0] & @TAB & $aRectHD[2] & @TAB & $iHDColWidth & @crlf) ConsoleWrite("-ListV" & @TAB & $iCol & @TAB & $aRectLV[0] & @TAB & $aRectLV[2] & @TAB & $iLVColWidth & @crlf) Next ConsoleWrite(@crlf) EndFunc ;==>Infos ;============================================== Func _resizeHeaderItems() ; after each horizontal scroll notification (function seems to work fine) Local $aRectLV For $iCol = 0 To _GUICtrlListView_GetColumnCount($g_hListView) - 1 If $iCol Then $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) Else $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, $iCol, $LVIR_LABEL) $aRectLV[0] -= (4 + $g_iIconWidth) EndIf _GUICtrlHeader_SetItemWidth( $g_hHeader, $iCol, $aRectLV[2] - (($aRectLV[0] > 0) ? $aRectLV[0] : 0) ) Next EndFunc ;==>_resizeHeaderItems ;============================================== 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 $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 while a header item is tracked (to be improved ?) . Also called from _reorderLVCols() Local $aRectHD, $aRectLV For $iCol = 0 To _GUICtrlListView_GetColumnCount($g_hListView) - 1 $aRectHD = _GUICtrlHeader_GetItemRect($g_hHeader, $iCol) If $iCol Then $aRectLV = _GUICtrlListView_GetSubItemRect($g_hListView, 0, $iCol) Else $aRectLV = _GUICtrlListView_GetItemRect($g_hListView, 0, $LVIR_LABEL) $aRectLV[0] -= (4 + $g_iIconWidth) EndIf If $aRectLV[0] < 0 And $aRectHD[2] > 0 Then $aRectHD[0] = $aRectLV[0] _GUICtrlListView_SetColumnWidth($g_hListview, $iCol, $aRectHD[2] - $aRectHD[0]) Next EndFunc ;==>_resizeLVCols2 ;============================================== Func _reorderLVCols() ; remove LVS_NOCOLUMNHEADER from listview __WinAPI_Set_Window_Style($g_hListView, $LVS_NOCOLUMNHEADER, False, False) ; 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_Set_Window_Style($g_hListView, $LVS_NOCOLUMNHEADER, True, False) _resizeLVCols2() EndFunc ;==>_reorderLVCols ;============================================== Func __WinAPI_Set_Window_Style($hWnd, $i_Style, $b_Add, $b_exStyle = False) ; compacted code (from Kafu's original) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local $iIndex = $b_exStyle ? $GWL_EXSTYLE : $GWL_STYLE ; $iIndex as named by msdn & help file Local $i_Style_Old = _WinAPI_GetWindowLong($hWnd, $iIndex) If $b_Add Then If BitAND($i_Style_Old, $i_Style) Then Return ; style already applied _WinAPI_SetWindowLong($hWnd, $iIndex, BitOR($i_Style_Old, $i_Style)) Else ; remove If Not BitAND($i_Style_Old, $i_Style) Then Return ; style not set _WinAPI_SetWindowLong($hWnd, $iIndex, BitXOR($i_Style_Old, $i_Style)) EndIf Local $iRet = _WinAPI_SetWindowPos($hWnd, $HWND_TOP, 0, 0, 0, 0, BitOR($SWP_FRAMECHANGED, $SWP_NOACTIVATE, $SWP_NOMOVE, $SWP_NOSIZE, $SWP_NOZORDER)) ; +++ If Not $iRet Then MsgBox($MB_TOPMOST, "_WinAPI_SetWindowPos", "Error = " & _WinAPI_GetLastError() & " Message = " & _WinAPI_GetLastErrorMessage()) EndFunc ;==>__WinAPI_Set_Window_Style ;============================================== 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_TRACK, $HDN_TRACKW 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) _resizeLVCols2() Return False ; to continue tracking the divider Case $HDN_ENDDRAG $g_bHeaderEndDrag = True Return False ; to allow the control to automatically place and reorder the item 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 _resizeHeaderItems() EndIf EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 10 Author Posted December 10 4 hours ago, pixelsearch said: I just tried this revised code, in case an icon is found in column 0 . Let's hope it will solve your alignment issue. Excellent work. Thank you. As always, your example works perfectly. I updated all of the changed functions in Files Au3. The header drag and drop to reorder listview columns is working great and the alignment is 100% now. So that was probably the most important part that is resolved. There is still an alignment problem with the horizontal scrolling for some reason. I don't really understand it. You may need to grab the latest FilesAu3-2025-12-10 that I just released because it has your latest fixes in there. This way you can reproduce it and you will likely understand what might be happening. To repo: Run Files Au3 and make some of the columns larger, then make the GUI smaller (width) to show the horizontal scrollbar in the listview. If you scroll all the way to the right, everything is aligned well. But when you scroll back to the left, that is when the alignment problem shows up. Scrolling back to the right again always fixes it. But left again is always a trigger for it. This likely isn't a high priority since there are only 3 columns (at the moment) in the listview. Users would really have to shrink the GUI and expand the columns more to trigger it. So if it's something that can be fixed, that would be great. If not, that is fine too. I feel like the header drag and drop issue (that you fixed) was more important and that is resolved now. Thank you so much. It's amazing how smooth this synchronization between separate header control and listview is and how cohesive it all is. Very impressive and unique, that's for certain. pixelsearch 1
pixelsearch Posted December 10 Posted December 10 @WildByDesign The 1st thing I notice in your last version "FilesAu3-2025-12-10" is this... ; resize listview columns to match header widths _resizeLVCols2() ...when it should be : ; resize listview columns to match header widths + update global variable $g_iIconWidth _resizeLVCols() This should fix some issues as $g_iIconWidth will be correctly defined (instead of keeping a value of 0) 1 hour ago, WildByDesign said: To repo: Run Files Au3 and make some of the columns larger, then make the GUI smaller (width) to show the horizontal scrollbar in the listview. I'll have to test this, having in mind that in my test script, the listview & header controls got a fixed width, no matter we enlarge the GUI or not. If something interesting comes out, I'll add a post here. WildByDesign 1 "I think you are searching a bug where there is no bug... don't listen to bad advice."
WildByDesign Posted December 10 Author Posted December 10 5 minutes ago, pixelsearch said: This should fix some issues as $g_iIconWidth will be correctly defined (instead of keeping a value of 0) I just wanted to confirm that this fixed the last remaining problem. I likely did a search and replace without checking carefully enough. Thanks for pointing that out. Everything is working as expected now.
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