WildByDesign Posted December 10 Posted December 10 This is for the Files Au3 - AutoIt File Manager project. If anyone could help me with subclassing the text color for a Header control, I would really appreciate it. Please keep in mind that this is a standalone Header control (_GUICtrlHeader_Create) and not the header of a ListView. There are several great examples in the forum for subclassing the text color for a header of a ListView control. Here are some examples: There is a LV header subclassing example by @UEZ in SampleControls.au3 in Dark Mode There is also a LV header subclassing example by @jpm over in this post in the DarkMode UDF thread I assume that what needs to be done for a standalone header control would be very similar, but some of the constants would certainly be different. I simply have no experience with the subclassing stuff and don't understand it at all. Thank you for your time. Here is an example with dark mode applied to the header already that could be used as a base before subclassing gets added. expandcollapse popup#include <SendMessage.au3> #include <WindowsNotifsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiHeader.au3> Global $g_hGUI, $g_hHeader Example() Func Example() ; Create a GUI with various controls. Local $g_hGUI = GUICreate("Dark Mode Header", 400, 400) ; Set background color GUISetBkColor(0x121212) ; create header $g_hHeader = _GUICtrlHeader_Create($g_hGUI) For $i = 0 To 2 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 80) Next ; apply dark mode to GUI and header DarkMode($g_hGUI, True) _WinAPI_SetWindowTheme_unr($g_hHeader, 'DarkMode_ItemsView', 'Header') ; Display the GUI. GUISetState(@SW_SHOW, $g_hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Delete the previous GUI and all controls. GUIDelete($g_hGUI) EndFunc ;==>Example ;-------------------------------------------------------------------------------------------------------------------------------- ; https://www.autoitscript.com/forum/topic/211475-darkmode-udf-for-autoits-win32guis/#comment-1530103 ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hGUI, $bDarkMode = True) ; DarkMode Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 ;ConsoleWrite("$DWMWA_USE_IMMERSIVE_DARK_MODE=" & $DWMWA_USE_IMMERSIVE_DARK_MODE & @CRLF) ; DWMWA_USE_IMMERSIVE_DARK_MODE ; https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute ; Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled. ; For compatibility reasons, all windows default to light mode regardless of the system setting. ; The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode. ; This value is supported starting with Windows 11 Build 22000. Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hGUI, $bDarkMode) ;_WinAPI_SetWindowTheme_unr(GUICtrlGetHandle($ChbxDrkMode), 0, 0) ; this control needs the theme EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode ; https://www.vbforums.com/showthread.php?900444-Windows-10-Dark-Mode-amp-VB6-apps If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) ; https://www.autoitscript.com/forum/index.php?showtopic=211475&view=findpost&p=1530103 DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 ; not needed ? _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) ; not needed ? EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; #include <WinAPITheme.au3> ; unthoughtful unrestricting mod. ;Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; #include <WinAPIGdi.au3> ; unthoughtful unrestricting mod. ;Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;--------------------------------------------------------------------------------------------------------------------------------
Nine Posted December 10 Posted December 10 (edited) Pretty much always the same. You need the handle of the subject and subclass it. Just need to know what notification you want to intercept. expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiHeader.au3> #include <WinAPI.au3> Global $g_hHeader Example() Func Example() ; Create a GUI with various controls. Local $hGUI = GUICreate("Dark Mode Header", 400, 400) ; Set background color GUISetBkColor(0x121212) ; create header $g_hHeader = _GUICtrlHeader_Create($hGUI) For $i = 0 To 2 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 80) Next Local $hDll = DllCallbackRegister(HeaderProc, 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') _WinAPI_SetWindowSubclass($g_hHeader, DllCallbackGetPtr($hDll), 1000, 0) ; apply dark mode to GUI and header (commented for smaller snippet) ;DarkMode($hGUI, True) ;_WinAPI_SetWindowTheme_unr($g_hHeader, 'DarkMode_ItemsView', 'Header') GUISetState() While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($g_hHeader, DllCallbackGetPtr($hDll), 1000) DllCallbackFree($hDll) EndFunc ;==>Example Func HeaderProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) If $iMsg = $WM_LBUTTONDOWN Then ConsoleWrite("click x : " & _WinAPI_LoWord($lParam) & " y : " & _WinAPI_HiWord($lParam) & @CRLF) Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>HeaderProc Edited December 10 by Nine ioa747 and WildByDesign 2 “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 December 10 Author Posted December 10 2 hours ago, Nine said: Pretty much always the same. You need the handle of the subject and subclass it. Just need to know what notification you want to intercept. Thank you. I tried my best with two different attempts by combining the code from other examples (which were ListView headers, specifically), but I could not get anything to work. Those examples seem to use the WM_NOTIFY message. Here was my last failed attempt: expandcollapse popup#include <SendMessage.au3> #include <WindowsNotifsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiHeader.au3> #include <WinAPIShellEx.au3> #include <WinAPIGdiDC.au3> Global $g_hGUI, $g_hHeader ; Dark Mode Colors (RGB) Global Const $COLOR_BG_DARK = 0x202020 Global Const $COLOR_TEXT_LIGHT = 0xFFFFFF Global Const $COLOR_CONTROL_BG = 0x2B2B2B Global Const $COLOR_EDIT_BG = 0x1E1E1E Global Const $COLOR_BUTTON_BG = 0x333333 Global Const $COLOR_BORDER = 0x3F3F3F ; Structure for NM_CUSTOMDRAW notification Global Const $tagNMCUSTOMDRAW = _ $tagNMHDR & ";" & _ ; Contains NM_CUSTOMDRAW / NMHDR header among other things "dword dwDrawStage;" & _ ; Current drawing stage (CDDS_*) "handle hdc;" & _ ; Device Context Handle "long left;long top;long right;long bottom;" & _ ; Drawing rectangle "dword_ptr dwItemSpec;" & _ ; Item index or other info (depending on the control) "uint uItemState;" & _ ; State Flags (CDIS_SELECTED, CDIS_FOCUS etc.) "lparam lItemlParam" ; lParam set by the item (e.g., via LVITEM.lParam) Example() Func Example() ; Create a GUI with various controls. Local $g_hGUI = GUICreate("Dark Mode Header", 400, 400) ; Set background color GUISetBkColor(0x121212) ; create header $g_hHeader = _GUICtrlHeader_Create($g_hGUI) For $i = 0 To 2 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 80) Next Local $hDll = DllCallbackRegister(HeaderProc, 'lresult', 'hwnd;uint;wparam;lparam;uint_ptr;dword_ptr') _WinAPI_SetWindowSubclass($g_hHeader, DllCallbackGetPtr($hDll), 1000, 0) ; apply dark mode to GUI and header DarkMode($g_hGUI, True) _WinAPI_SetWindowTheme_unr($g_hHeader, 'DarkMode_ItemsView', 'Header') ; Display the GUI. GUISetState(@SW_SHOW, $g_hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd _WinAPI_RemoveWindowSubclass($g_hHeader, DllCallbackGetPtr($hDll), 1000) DllCallbackFree($hDll) ; Delete the previous GUI and all controls. GUIDelete($g_hGUI) EndFunc ;==>Example Func HeaderProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData) ;If $iMsg = $WM_LBUTTONDOWN Then ConsoleWrite("click x : " & _WinAPI_LoWord($lParam) & " y : " & _WinAPI_HiWord($lParam) & @CRLF) ;Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) Switch $iMsg Case $WM_NOTIFY Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) Local $hFrom = $tNMHDR.hWndFrom Local $iCode = $tNMHDR.Code ; --- Adjust ListView Header text color --- If $iCode = $NM_CUSTOMDRAW Then Local $tNMCUSTOMDRAW = DllStructCreate($tagNMCUSTOMDRAW, $lParam) Local $dwDrawStage = $tNMCUSTOMDRAW.dwDrawStage Local $hDC = $tNMCUSTOMDRAW.hdc Switch $dwDrawStage Case $CDDS_PREPAINT Return $CDRF_NOTIFYITEMDRAW Case $CDDS_ITEMPREPAINT _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT)) ; White text _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($COLOR_BG_DARK)) ; Dark background Return BitOR($CDRF_NEWFONT, $CDRF_NOTIFYPOSTPAINT) EndSwitch EndIf Case $WM_PAINT ; Custom Paint for better Dark Mode rendering Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndSwitch ; Forward standard message to DefSubclassProc Return _WinAPI_DefSubclassProc($hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>HeaderProc Func _ColorToCOLORREF($iColor) ;RGB to BGR Local $iR = BitAND(BitShift($iColor, 16), 0xFF) Local $iG = BitAND(BitShift($iColor, 8), 0xFF) Local $iB = BitAND($iColor, 0xFF) Return BitOR(BitShift($iB, -16), BitShift($iG, -8), $iR) EndFunc ;==>_ColorToCOLORREF ;-------------------------------------------------------------------------------------------------------------------------------- ; https://www.autoitscript.com/forum/topic/211475-darkmode-udf-for-autoits-win32guis/#comment-1530103 ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hGUI, $bDarkMode = True) ; DarkMode Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 ;ConsoleWrite("$DWMWA_USE_IMMERSIVE_DARK_MODE=" & $DWMWA_USE_IMMERSIVE_DARK_MODE & @CRLF) ; DWMWA_USE_IMMERSIVE_DARK_MODE ; https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute ; Use with DwmSetWindowAttribute. Allows the window frame for this window to be drawn in dark mode colors when the dark mode system setting is enabled. ; For compatibility reasons, all windows default to light mode regardless of the system setting. ; The pvAttribute parameter points to a value of type BOOL. TRUE to honor dark mode for the window, FALSE to always use light mode. ; This value is supported starting with Windows 11 Build 22000. Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hGUI, $bDarkMode) ;_WinAPI_SetWindowTheme_unr(GUICtrlGetHandle($ChbxDrkMode), 0, 0) ; this control needs the theme EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode ; https://www.vbforums.com/showthread.php?900444-Windows-10-Dark-Mode-amp-VB6-apps If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) ; https://www.autoitscript.com/forum/index.php?showtopic=211475&view=findpost&p=1530103 DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 ; not needed ? _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) ; not needed ? EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; #include <WinAPITheme.au3> ; unthoughtful unrestricting mod. ;Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; #include <WinAPIGdi.au3> ; unthoughtful unrestricting mod. ;Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;--------------------------------------------------------------------------------------------------------------------------------
Solution ioa747 Posted December 10 Solution Posted December 10 (edited) my effort to learn expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiHeader.au3> #include <WinAPI.au3> ; === Global Variables and Constants === Global $g_hGUI, $g_hHeader Global $g_hOldGUIProc = 0 ; Storage for the original GUI Window pointer. Global $g_hGUISubclass Global Const $CLR_WHITE = 0xFFFFFF ; The text color ; Structure Definitions (using $tagNMHDR and $tagRECT which are defined in includes) Global Const $tagNMCUSTOMDRAW = $tagNMHDR & ";dword DrawStage;handle hdc;" & $tagRECT & ";dword_ptr ItemSpec;uint ItemState;lparam lItemParam;" Example() Func Example() ; Create a GUI with various controls. $g_hGUI = GUICreate("Dark Mode Header", 400, 400) ; Set background color GUISetBkColor(0x121212) ; dummy button for stealing 1st focus GUICtrlCreateButton("dummy", -100, 0, 10, 10) ; create header $g_hHeader = _GUICtrlHeader_Create($g_hGUI) For $i = 0 To 2 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 80) Next ; apply dark mode to GUI and header DarkMode($g_hGUI, True) _WinAPI_SetWindowTheme_unr($g_hHeader, 'DarkMode_ItemsView', 'Header') ; === SUBCLASSING THE PARENT GUI === ; Register the callback function to intercept WM_NOTIFY messages from the header. $g_hGUISubclass = DllCallbackRegister("_GUISubclass", "ptr", "hwnd;uint;wparam;lparam") ; Subclass the Parent GUI window (using the built-in $GWL_WNDPROC). $g_hOldGUIProc = _WinAPI_SetWindowLong($g_hGUI, $GWL_WNDPROC, DllCallbackGetPtr($g_hGUISubclass)) ; -------------------------------------- ; Display the GUI. GUISetState(@SW_SHOW, $g_hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Restore the original window procedure and free Dll resources before exiting. _WinAPI_SetWindowLong($g_hGUI, $GWL_WNDPROC, $g_hOldGUIProc) DllCallbackFree($g_hGUISubclass) ; Delete the previous GUI and all controls. GUIDelete($g_hGUI) EndFunc ;==>Example ; Intercepts WM_NOTIFY messages from the Header control to set the text color for dark mode. Func _GUISubclass($hWnd, $iMsg, $wParam, $lParam) ; Check if the message is WM_NOTIFY If $iMsg = $WM_NOTIFY Then Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) ; Check if the notification is from the Header control AND is a Custom Draw message. If $tNMHDR.hwndfrom = $g_hHeader And $tNMHDR.code = $NM_CUSTOMDRAW Then Local $tNMCustomDraw = DllStructCreate($tagNMCUSTOMDRAW, $lParam) ; STEP 1: Intercept Pre-Paint (Value 1). Request item notifications. If $tNMCustomDraw.DrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW ; Tell the system to send CDDS_ITEMPREPAINT next. EndIf ; STEP 2: Intercept Item Pre-Paint (Value 65537). Set the text color. If BitAND($tNMCustomDraw.DrawStage, $CDDS_ITEMPREPAINT) Then ; Set the text color to white _WinAPI_SetTextColor($tNMCustomDraw.hdc, $CLR_WHITE) ; Tell the system to use the new font settings and continue. Return $CDRF_NEWFONT EndIf EndIf EndIf ; Pass the message to the original Window Procedure Return _WinAPI_CallWindowProc($g_hOldGUIProc, $hWnd, $iMsg, $wParam, $lParam) EndFunc ;==>_GUISubclass ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hGUI, $bDarkMode = True) ; DarkMode ; Sets the main GUI window to use immersive dark mode. Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hGUI, $bDarkMode) EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. ; Helper function to apply dark mode theme to controls within the window. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;-------------------------------------------------------------------------------------------------------------------------------- Edited December 10 by ioa747 remove extra #include I know that I know nothing
WildByDesign Posted December 10 Author Posted December 10 29 minutes ago, ioa747 said: my effort to learn This is phenomenal work. And for my own learning part of this process, your comments every step of the way throughout your example is extremely beneficial. I've read the code comments but I'm going to go through it a few more times to make sure that I take in all of the complex details. Thank you for your help and for your time. I appreciate it. ioa747 1
ioa747 Posted December 10 Posted December 10 (edited) simplification to GUIRegisterMsg expandcollapse popup#include <GUIConstantsEx.au3> #include <GuiHeader.au3> #include <WinAPI.au3> ; === Global Variables and Constants === Global $g_hGUI, $g_hHeader Global Const $CLR_WHITE = 0xFFFFFF ; The text color ; Structure Definitions (using $tagNMHDR and $tagRECT which are defined in includes) Global Const $tagNMCUSTOMDRAW = $tagNMHDR & ";dword DrawStage;handle hdc;" & $tagRECT & ";dword_ptr ItemSpec;uint ItemState;lparam lItemParam;" Example() Func Example() ; Create a GUI with various controls. $g_hGUI = GUICreate("Dark Mode Header", 400, 400) ; Set background color GUISetBkColor(0x121212) ; dummy button for stealing 1st focus GUICtrlCreateButton("dummy", -100, 0, 10, 10) ; create header $g_hHeader = _GUICtrlHeader_Create($g_hGUI) For $i = 0 To 2 _GUICtrlHeader_AddItem($g_hHeader, "Column" & $i, 80) Next ; apply dark mode to GUI and header DarkMode($g_hGUI, True) _WinAPI_SetWindowTheme_unr($g_hHeader, 'DarkMode_ItemsView', 'Header') GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY_Handler") ; Display the GUI. GUISetState(@SW_SHOW, $g_hGUI) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; Delete the previous GUI and all controls. GUIDelete($g_hGUI) EndFunc ;==>Example Func WM_NOTIFY_Handler($hWnd, $iMsg, $wParam, $lParam) ; Check if the message is WM_NOTIFY If $iMsg = $WM_NOTIFY Then Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam) ; === HEADER LOGIC === If $tNMHDR.hwndfrom = $g_hHeader And $tNMHDR.code = $NM_CUSTOMDRAW Then Local $tNMCustomDraw = DllStructCreate($tagNMCUSTOMDRAW, $lParam) ; STEP 1 (CDDS_PREPAINT): Request item notifications. If $tNMCustomDraw.DrawStage = $CDDS_PREPAINT Then Return $CDRF_NOTIFYITEMDRAW EndIf ; STEP 2 (CDDS_ITEMPREPAINT): Set text color. If BitAND($tNMCustomDraw.DrawStage, $CDDS_ITEMPREPAINT) Then ; Set the text color to white _WinAPI_SetTextColor($tNMCustomDraw.hdc, $CLR_WHITE) ; Tell the system to use the new font settings and continue. Return $CDRF_NEWFONT EndIf EndIf ; === LISTVIEW LOGIC === ;... EndIf ; Pass all other messages to the default window procedure. Return $GUI_RUNDEFMSG EndFunc ;==>WM_NOTIFY_Handler ;-------------------------------------------------------------------------------------------------------------------------------- Func DarkMode($hGUI, $bDarkMode = True) ; DarkMode ; Sets the main GUI window to use immersive dark mode. Local Enum $DWMWA_USE_IMMERSIVE_DARK_MODE = (@OSBuild <= 18985) ? 19 : 20 Local $iRet = _WinAPI_DwmSetWindowAttribute_unr($hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, $bDarkMode) If Not $iRet Then Return SetError(1, 0, -1) _SetCtrlColorMode($hGUI, $bDarkMode) EndFunc ;==>DarkMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _SetCtrlColorMode($hWnd, $bDarkMode = True, $sName = Default) ; 'Explorer', 'CFD', 'DarkMode_ItemsView', etc. ; Helper function to apply dark mode theme to controls within the window. If $sName = Default Then $sName = $bDarkMode ? 'DarkMode_Explorer' : 'Explorer' $bDarkMode = Not Not $bDarkMode If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) Local Enum $eDefault, $eAllowDark, $eForceDark, $eForceLight, $eMax ; enum PreferredAppMode DllCall('uxtheme.dll', 'bool', 133, 'hwnd', $hWnd, 'bool', $bDarkMode) ; fnAllowDarkModeForWindow = 133 DllCall('uxtheme.dll', 'int', 135, 'int', ($bDarkMode ? $eForceDark : $eForceLight)) ; fnAllowDarkModeForApp = 135 _WinAPI_SetWindowTheme_unr($hWnd, $sName) DllCall('uxtheme.dll', 'none', 104) ; fnRefreshImmersiveColorPolicyState = 104 _SendMessage($hWnd, $WM_THEMECHANGED, 0, 0) EndFunc ;==>_SetCtrlColorMode ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_SetWindowTheme_unr($hWnd, $sName = Null, $sList = Null) ; Causes a window to use a different set of visual style information than its class normally uses Local $sResult = DllCall('UxTheme.dll', 'long', 'SetWindowTheme', 'hwnd', $hWnd, 'wstr', $sName, 'wstr', $sList) If @error Then Return SetError(@error, @extended, 0) If $sResult[0] Then Return SetError(10, $sResult[0], 0) Return 1 EndFunc ;==>_WinAPI_SetWindowTheme_unr ;-------------------------------------------------------------------------------------------------------------------------------- Func _WinAPI_DwmSetWindowAttribute_unr($hWnd, $iAttribute, $iData) ; Sets the value of the specified attributes for non-client rendering to apply to the window Local $aCall = DllCall('dwmapi.dll', 'long', 'DwmSetWindowAttribute', 'hwnd', $hWnd, 'dword', $iAttribute, _ 'dword*', $iData, 'dword', 4) If @error Then Return SetError(@error, @extended, 0) If $aCall[0] Then Return SetError(10, $aCall[0], 0) Return 1 EndFunc ;==>_WinAPI_DwmSetWindowAttribute_unr ;-------------------------------------------------------------------------------------------------------------------------------- Edited December 10 by ioa747 WildByDesign 1 I know that I know nothing
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