Nine Posted May 4 Posted May 4 (edited) Ok, I am quite busy at the moment, so I don't have time to clean up and optimize. expandcollapse popup#AutoIt3Wrapper_UseX64=y ; From Nine #include <GuiConstants.au3> #include <GuiHeader.au3> #include <WinAPI.au3> #include <Misc.au3> #include <WinAPITheme.au3> #include <GuiListView.au3> DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext", "HWND", "DPI_AWARENESS_CONTEXT" - 2) Global $mHeader[] Example() Func Example() Local $hGUI = GUICreate("Header ", 500, 300) GUISetBkColor(0x000000) Local $idListView = GUICtrlCreateListView("Items List|SubItems1|SubItems2", 10, 10, 480, 280, -1, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT)) Local $hListView = GUICtrlGetHandle($idListView) Local $hHeader = GUICtrlSendMsg($idListView, $LVM_GETHEADER, 0, 0) _WinAPI_SetWindowTheme($hListView, "DarkMode_Explorer") ; PROBLEM: cause of random GUI crashes _WinAPI_SetWindowTheme($hHeader, "DarkMode_ItemsView", "Header") ; No problem with dark mode header theme GUICtrlSetBkColor($idListView, 0x121212) GUICtrlSetColor($idListView, 0xFFFFFF) Local $iCount = _GUICtrlListView_GetColumnCount($hListView), $aHeader[$iCount] For $i = 0 To $iCount - 1 $aHeader[$i] = _GUICtrlListView_GetColumn($hListView, $i)[5] Next $mHeader[$idListView] = $aHeader Local $hSubClass = DllCallbackRegister(WM_NOTIFY, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), _WinAPI_MakeLong($hSubClass, $idListView), $hHeader) _WinAPI_SetWindowSubclass($hHeader, DllCallbackGetPtr($hSubClass), 1000, $hHeader) For $i = 1 To 20 GUICtrlCreateListViewItem("item" & $i & "|item" & $i & "|item" & $i, $idListView) Next _GUICtrlListView_SetColumnWidth($idListView, 2, $LVSCW_AUTOSIZE_USEHEADER) _WinAPI_DwmSetWindowAttributeEx($hGUI, 20, 1) ; Apply Acrylic material on newer Windows 11 builds If @OSBuild >= 22621 Then _WinAPI_DwmSetWindowAttributeEx($hGUI, 38, 3) _WinAPI_DwmExtendFrameIntoClientArea($hGUI, _WinAPI_CreateMargins(-1, -1, -1, -1)) EndIf GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hHeader, DllCallbackGetPtr($hSubClass), 1000) _WinAPI_RemoveWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), _WinAPI_MakeLong($hSubClass, $idListView)) DllCallbackFree($hSubClass) EndFunc ;==>Example Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) Local Static $bHover, $tPoint Local $hBrush Switch $iMsg Case $WM_NOTIFY Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Switch $tNMHDR.Code Case $NM_CUSTOMDRAW If _WinAPI_GetClassName($tNMHDR.hWndFrom) = "sysheader32" Then Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Switch $tCustDraw.dwDrawStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tCustDraw, "Left")) _WinAPI_SetBkMode($tCustDraw.hDC, 1) _WinAPI_SetTextColor($tCustDraw.hDC, 0xFFFFFF) If $bHover And _WinAPI_PtInRect($tRect, $tPoint) Then $hBrush = _WinAPI_CreateSolidBrush(_IsPressed($VK_LBUTTON) ? 0x404040 : 0x303030) Else $hBrush = _WinAPI_CreateSolidBrush(0x202020) EndIf _WinAPI_InflateRect($tRect, -1, 0) _WinAPI_FillRect($tCustDraw.hDC, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) _WinAPI_InflateRect($tRect, -5, -2) _WinAPI_DrawText($tCustDraw.hDC, ($mHeader[_WinAPI_HiWord($iID)])[$tCustDraw.dwItemSpec], $tRect, BitOR($DT_LEFT, $DT_NOCLIP)) Return $CDRF_SKIPDEFAULT EndSwitch EndIf ;Case $HDN_BEGINTRACKW ; $bHover = False ; _WinAPI_RemoveWindowSubclass($pData, DllCallbackGetPtr(_WinAPI_LoWord($iID)), 1000) ;Case $HDN_ENDTRACKW ; _WinAPI_SetWindowSubclass($pData, DllCallbackGetPtr(_WinAPI_LoWord($iID)), 1000, $pData) EndSwitch Case $WM_MOUSEMOVE If $pData = $hWnd Then $bHover = True $tPoint = _WinAPI_GetMousePos(True, $hWnd) _WinAPI_InvalidateRect($hWnd, 0, False) _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) EndIf Case $WM_MOUSELEAVE If $pData = $hWnd Then $bHover = False _WinAPI_InvalidateRect($hWnd, 0, False) EndIf EndSwitch Return __WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>WM_NOTIFY Func _WinAPI_DwmSetWindowAttributeEx($hWnd, $iAttribute, $iData) Switch $iAttribute Case 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, $DWMWA_USE_IMMERSIVE_DARK_MODE, 33, 34, 35, 36, 37, 38, 39, 40 Case Else Return SetError(1, 0, 0) EndSwitch Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error + 10, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttributeEx Func __WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Return DllCall('comctl32.dll', 'lresult', 'DefSubclassProc', 'hwnd', $hWnd, 'uint', $iMsg, 'wparam', $wParam, 'lparam', $lParam)[0] EndFunc You can have with this approach as many LV in a single GUI as you want, you just need to register each one in the global map... Edited May 4 by Nine ioa747 and WildByDesign 1 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
WildByDesign Posted May 4 Author Posted May 4 7 hours ago, Nine said: You can have with this approach as many LV in a single GUI as you want, you just need to register each one in the global map... This is brilliant! Thank you. I just wanted to confirm a few things. Since we were able to get rid of cases for $HDN_BEGINTRACKW and $HDN_ENDTRACKW after the fixes: Does that mean that we can switch anything that is HiWord/LoWord related? ;_WinAPI_SetWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), _WinAPI_MakeLong($hSubClass, $idListView), $hHeader) _WinAPI_SetWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), $idListView, $hHeader) ;_WinAPI_RemoveWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), _WinAPI_MakeLong($hSubClass, $idListView)) _WinAPI_RemoveWindowSubclass($hListView, DllCallbackGetPtr($hSubClass), $idListView) ;_WinAPI_DrawText($tCustDraw.hDC, ($mHeader[_WinAPI_HiWord($iID)])[$tCustDraw.dwItemSpec], $tRect, BitOR($DT_LEFT, $DT_NOCLIP)) _WinAPI_DrawText($tCustDraw.hDC, ($mHeader[$iID])[$tCustDraw.dwItemSpec], $tRect, BitOR($DT_LEFT, $DT_NOCLIP)) Are those changes (above) safe changes to make?
Nine Posted May 4 Posted May 4 2 hours ago, WildByDesign said: Are those changes (above) safe changes to make? Yes. Since we do not need to set and remove the subclass, $hSubclass becomes useless in the subclass proc. WildByDesign 1 “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Debug Messages Monitor UDF Screen Scraping Round Corner GUI UDF Multi-Threading Made Easy Interface Object based on Tag
jugador Posted May 4 Posted May 4 (edited) On 4/28/2026 at 10:43 PM, jugador said: Keep _GUICtrlHeader_GetItemText($tCustDraw.hWndFrom, $tCustDraw.dwItemSpec) as it is, omit $hHeader Subclass lines, and use the DefSubclassProc fix. I think this will solve the crash. infinite recursion loop caused the script in this post to crash. Here is how to solve it. expandcollapse popup#include <GuiConstants.au3> #include <GuiHeader.au3> #include <WinAPI.au3> #include <Misc.au3> #include <WinAPITheme.au3> #include <GuiListView.au3> AutoItSetOption("MustDeclareVars", 1) Global $hUser32Dll = DllOpen("user32.dll") Example() Func Example() Local $hGUI = GUICreate("Header Subclass", 500, 300) GUISetBkColor(0x000000) Local $idListView = GUICtrlCreateListView("Items List|SubItems1|SubItems2", 10, 10, 480, 280, $LVS_REPORT, BitOR($LVS_EX_DOUBLEBUFFER, $LVS_EX_FULLROWSELECT, $LVS_EX_HEADERDRAGDROP)) Local $hListView = GUICtrlGetHandle($idListView) Local $hHeader = _GUICtrlListView_GetHeader($hListView) _WinAPI_SetWindowTheme($hListView, "DarkMode_Explorer") _WinAPI_SetWindowTheme($hHeader, "DarkMode_ItemsView", "Header") GUICtrlSetBkColor($idListView, 0x121212) GUICtrlSetColor($idListView, 0xFFFFFF) GUICtrlCreateListViewItem("item1|item1|item1", $idListview) GUICtrlCreateListViewItem("item2|item2|item2", $idListview) GUICtrlCreateListViewItem("item3|item3|item3", $idListview) _GUICtrlListView_SetColumnWidth($idListView, 2, $LVSCW_AUTOSIZE_USEHEADER) Local $hSubClass = DllCallbackRegister(_Header_Subclass, "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr") _WinAPI_SetWindowSubclass($hHeader, DllCallbackGetPtr($hSubClass), 1000, $hHeader) GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE _WinAPI_RemoveWindowSubclass($hHeader, DllCallbackGetPtr($hSubClass), 1000) DllCallbackFree($hSubClass) DllClose($hUser32Dll) EndFunc Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam) Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hWndFrom = HWnd($tNMHDR.hWndFrom) Local $iCode = $tNMHDR.Code If _WinAPI_GetClassName($hWndFrom) = "sysheader32" Then Switch $iCode Case $NM_CUSTOMDRAW Local $tCustDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam) Switch $tCustDraw.dwDrawStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT Local $hDC = $tCustDraw.hDC Local $tRect = DllStructCreate($tagRECT, DllStructGetPtr($tCustDraw, "Left")) Local $tPoint = _WinAPI_GetMousePos(True, $hWndFrom) Local $iColor = 0x121212 If _WinAPI_PtInRect($tRect, $tPoint) Then $iColor = _IsPressed(0x01, $hUser32Dll) ? 0x252525 : 0x383838 EndIf Local $hBrush = _WinAPI_CreateSolidBrush($iColor) _WinAPI_FillRect($hDC, $tRect, $hBrush) _WinAPI_DeleteObject($hBrush) _WinAPI_SetBkMode($hDC, 1) _WinAPI_SetTextColor($hDC, 0xFFFFFF) _WinAPI_InflateRect($tRect, -5, -2) _WinAPI_DrawText($tCustDraw.hDC, _GUICtrlHeader_GetItemText($tCustDraw.hWndFrom, $tCustDraw.dwItemSpec), $tRect, BitOR($DT_LEFT, $DT_NOCLIP)) Return $CDRF_SKIPDEFAULT EndSwitch EndSwitch EndIf Return $GUI_RUNDEFMSG EndFunc Func _Header_Subclass($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) #forceref $iID, $pData Switch $iMsg Case $WM_MOUSEMOVE _WinAPI_TrackMouseEvent($hWnd, $TME_LEAVE) _WinAPI_InvalidateRect($hWnd) Case $WM_MOUSELEAVE _WinAPI_InvalidateRect($hWnd) EndSwitch Return __WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc Func __WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Return DllCall('comctl32.dll', 'lresult', 'DefSubclassProc', 'hwnd', $hWnd, 'uint', $iMsg, 'wparam', $wParam, _ 'lparam', $lParam)[0] EndFunc ;==>_WinAPI_DefSubclassProc Edited May 5 by jugador
WildByDesign Posted May 4 Author Posted May 4 3 hours ago, jugador said: infinite recursion loop cause of crash: I don't completely understand what the root of the infinite recursion loop is. But from this example, the $CDDS_ITEMPREPAINT case is never entered and no coloring is done on the header and therefore is never reaching the _WinAPI_DrawText function that contains the _GUICtrlHeader_GetItemText which was causing crashes. I can only see the initial $CDDS_PREPAINT case being used here.
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