WildByDesign Posted Thursday at 11:38 PM Posted Thursday at 11:38 PM I wanted to create a dark mode menubar without requiring ModernMenuRaw UDF which uses Ownerdrawn menubar. The problem with Ownerdrawn menubar is that it always leaves a single pixel white line across the entire bottom of the menubar which is part of the non-client area and therefore no perfect method for permanently removing it. Screenshot: Code: expandcollapse popup#NoTrayIcon #include <GuiMenu.au3> #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> #include <StaticConstants.au3> #include <Array.au3> #include "_WinAPI_DPI.au3" #include "GuiFlatButton_menu.au3" Opt("GUIOnEventMode", 1) Global $iDPI1, $iDPI2, $hGUI Global $aWinPos, $aClientSize, $iCaptionHeight Global $iMenubarBk = 0x202020 Global $iMenubarHov = 0x404040 Global $iMenubarSel = 0x404040 Global $iPadding = 20 Global $hFileMenu, $hEditMenu, $hHelpMenu, $iMenuHeight Global $iDPI = _WinAPI_SetDPIAwareness(), $iDPI_def = 96 If $iDPI = 0 Then Exit MsgBox($MB_ICONERROR, "ERROR", "Unable to set DPI awareness!!!", 10) $iDPI1 = $iDPI / $iDPI_def $iDPI2 = $iDPI_def / $iDPI ;GuiFlatButton_SetDefaultColors(0x000000, 0xFFFFFF, 0x000000) ;set default colors of future buttons Local $aColorsEx = _ [$iMenubarBk, 0xFFFFFF, $iMenubarBk, _ ; normal : Background, Text, Border $iMenubarBk, 0xFFFFFF, $iMenubarBk, _ ; focus : Background, Text, Border $iMenubarHov, 0xFFFFFF, $iMenubarHov, _ ; hover : Background, Text, Border $iMenubarSel, 0xFFFFFF, $iMenubarSel] ; selected : Background, Text, Border GuiFlatButton_SetDefaultColorsEx($aColorsEx) ;DllCall("User32.dll", "bool", "SetProcessDpiAwarenessContext" , "HWND", "DPI_AWARENESS_CONTEXT" -4) _GUI_Start() Func _GUI_Start() $hFileMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hFileMenu, 0, "Exit", 1) $hEditMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hEditMenu, 0, "Undo", 1) _GUICtrlMenu_InsertMenuItem($hEditMenu, 1, "Copy", 2) _GUICtrlMenu_InsertMenuItem($hEditMenu, 2, "Paste", 3) $hHelpMenu = _GUICtrlMenu_CreatePopup() _GUICtrlMenu_InsertMenuItem($hHelpMenu, 0, "View Help", 1) _GUICtrlMenu_InsertMenuItem($hHelpMenu, 1, "About Program", 2) $hGUI = GUICreate("Dark Menubar - concept") GUISetBkColor(0x101010) ;GuiDarkmodeApply($hGUI) DarkMode($hGUI, True) GUISetFont(10, $FW_NORMAL, -1, "Segoe UI") GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents") $aWinPos = WinGetPos($hGUI) $aClientSize = WinGetClientSize($hGUI) $idFileMenu = GuiFlatButton_Create("File", -2, -2, -1, -1, $SS_CENTER) GUICtrlSetOnEvent(-1, "idFileMenu") ; get initial position $aPos = ControlGetPos($hGUI, "", $idFileMenu) GuiFlatButton_SetPos($idFileMenu, $aPos[0], $aPos[1], $aPos[2] + $iPadding, $aPos[3]) ; get position after padding $aPos = ControlGetPos($hGUI, "", $idFileMenu) $iMenuHeight = $aPos[3] - 2 $idMenuBar = GUICtrlCreateLabel(" ", 0, 0, $aClientSize[1], $aPos[3] - 2, $WS_CLIPSIBLINGS) GUICtrlSetBkColor(-1, $iMenubarBk) $idEditMenu = GuiFlatButton_Create("Edit", $aPos[0] + $aPos[2], -2, -1, -1, $SS_CENTER) GUICtrlSetOnEvent(-1, "idEditMenu") ; get initial position $aPos = ControlGetPos($hGUI, "", $idEditMenu) GuiFlatButton_SetPos($idEditMenu, $aPos[0], $aPos[1], $aPos[2] + $iPadding, $aPos[3]) ; get position after padding $aPos = ControlGetPos($hGUI, "", $idEditMenu) $idHelpMenu = GuiFlatButton_Create("Help", $aPos[0] + $aPos[2], -2, -1, -1, $SS_CENTER) GUICtrlSetOnEvent(-1, "idHelpMenu") ; get initial position $aPos = ControlGetPos($hGUI, "", $idHelpMenu) GuiFlatButton_SetPos($idHelpMenu, $aPos[0], $aPos[1], $aPos[2] + $iPadding, $aPos[3]) ; get position after padding $aPos = ControlGetPos($hGUI, "", $idHelpMenu) $aCtrlPos = ControlGetPos($hGUI, "", $idFileMenu) ;GUISetState(@SW_SHOW) $iCaptionHeight = _TitleBarSize($hGUI) ConsoleWrite("titlebar height: " & $iCaptionHeight & @CRLF) GUISetState(@SW_SHOW) ; Just idle around While 1 Sleep(1000) WEnd EndFunc Func idFileMenu() ; need to redo sizes here in case window moved $aWinPos = WinGetPos($hGUI) $MenuResult = _GUICtrlMenu_TrackPopupMenu($hFileMenu, $hGUI, $aWinPos[0] + 2, $aWinPos[1] + $iCaptionHeight + $iMenuHeight, 1, 1, 2) Switch $MenuResult Case 0 ConsoleWrite("menu has been clicked away" & @CRLF) Case 1 Exit EndSwitch EndFunc Func idEditMenu() ; need to redo sizes here in case window moved $aWinPos = WinGetPos($hGUI) $MenuResult = _GUICtrlMenu_TrackPopupMenu($hEditMenu, $hGUI, $aWinPos[0] + 2 + 52, $aWinPos[1] + $iCaptionHeight + $iMenuHeight, 1, 1, 2) Switch $MenuResult Case 0 ConsoleWrite("menu has been clicked away" & @CRLF) Case 1 ConsoleWrite("You clicked on Undo" & @CRLF) Case 2 ConsoleWrite("You clicked on Copy" & @CRLF) Case 3 ConsoleWrite("You clicked on Paste" & @CRLF) EndSwitch EndFunc Func idHelpMenu() ; need to redo sizes here in case window moved $aWinPos = WinGetPos($hGUI) $MenuResult = _GUICtrlMenu_TrackPopupMenu($hHelpMenu, $hGUI, $aWinPos[0] + 2 + 52 + 52, $aWinPos[1] + $iCaptionHeight + $iMenuHeight, 1, 1, 2) Switch $MenuResult Case 0 ConsoleWrite("menu has been clicked away" & @CRLF) Case 1 ConsoleWrite("You clicked on View Help" & @CRLF) Case 2 ConsoleWrite("You clicked on About Program" & @CRLF) MsgBox(0, "About Program", "Cool Program Name" & @CRLF & @CRLF & "Version: 1.0" & @CRLF & "Created by: WildByDesign") EndSwitch EndFunc Func SpecialEvents() Select Case @GUI_CtrlId = $GUI_EVENT_CLOSE Exit EndSelect EndFunc Func _TitleBarSize($hWnd) Static $iFrame = _WinAPI_GetSystemMetrics( 32) Static $iBorder = _WinAPI_GetSystemMetrics( 5) $tWinRect = _WinAPI_GetWindowRect( $hWnd) $tClientRect = _WinAPI_GetClientRect( $hWnd) $iWinHeight = DllStructGetData( $tWinRect, "Bottom") - DllStructGetData( $tWinRect, "Top") $iClientHeight = DllStructGetData( $tClientRect, "Bottom") - DllStructGetData( $tClientRect, "Top") $iTitleBarSize = ($iWinHeight - $iClientHeight - $iFrame - $iBorder) * $iDPI1 Return $iTitleBarSize EndFunc ;-------------------------------------------------------------------------------------------------------------------------------- ; 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($Button_OK, $bDarkMode) ;_SetCtrlColorMode($Button_copy, $bDarkMode) _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 ;-------------------------------------------------------------------------------------------------------------------------------- UDF's Required: _WinAPI_DPI.au3GuiFlatButton_menu.au3 If anybody has any interest in this and wants to collaborate, I would love that. One thing that is lacking is the ability to easily move from menu to menu when you have one already open. Eg. You have a menu open and hover over the other menus. In most programs, it would automatically open those. I am sure that it is possible to do this but it is beyond my skill level. Danyfirex 1
WildByDesign Posted 6 hours ago Author Posted 6 hours ago I ended up using this same technique of using _GUICtrlMenu_TrackPopupMenu to control the exact placement of a context/popup menu for a statusbar item recently as well with excellent results. Link: https://github.com/WildByDesign/ImmersiveUX/blob/main/ImmersiveUX.au3#L865 Measurement was easier for that though because it was the bottom of the GUI and so titlebar did not need to be calculated in this case. ioa747 1
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