Jump to content

Recommended Posts

Posted (edited)

I tried to apply dark mode to the SampleControls.au3 example.

What I did so far:

; Coded by UEZ build 2025-10-16 beta
;not DPI aware!

#include <APIConstants.au3>
#include <AVIConstants.au3>
#include <GUIConstantsEx.au3>
#include <TreeViewConstants.au3>
#include <ListViewConstants.au3>
#include <GuiMenu.au3>
#include <GuiScrollBars.au3>
#include <GuiTab.au3>
#include <WinAPIConstants.au3>
#include <WinAPIGdi.au3>
#include <WinAPIRes.au3>
#include <WinAPIShellEx.au3>
#include <WinAPISys.au3>
#include <WinAPISysWin.au3>
#include <WinAPITheme.au3>
#include <WindowsConstants.au3>

Enum $IHCM_USE_CACHED_VALUE, $IHCM_REFRESH
Enum $APPMODE_DEFAULT = 0, $APPMODE_ALLOWDARK, $APPMODE_FORCEDARK, $APPMODE_FORCELIGHT, $APPMODE_MAX
Const $PRF_CLIENT = 0x04

; 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

; Global variables for subclassing (MUST be declared before _Example()!)
Global $g_hGUI = 0, $g_hTab, $g_ListView
Global $g_aControls[50][3] = [[0, 0, 0]] ; [ControlID, hWnd, OldWndProc]
Global $g_iControlCount = 0
Global $g_pSubclassProc = 0

; Global brushes for _WM_CTLCOLOR (avoids memory leaks)
Global $g_hBrushEdit = 0
Global $g_hBrushButton = 0
Global $g_hBrushBg = 0
Global $g_hBrushGreen
Global $g_hLabelGreen = 0, $g_idLabelGreen
Global $g_idLabelPic, $g_hLabelPic
Global $g_hMenu = 0

; Global variable for tab subclassing
Global $g_hTab_CB, $g_pTab_CB, $g_hProc

; 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)


Global $g_hMenu = 0, $hMenuFont
Global $g_aMenuText = [] ; dynamic array for top-level menu texts
Global $arMenuItems[1][8]
$arMenuItems[0][0] = 0
Global $arSideItems[1][10]
$arSideItems[0][0] = 0

Const $ODT_MENU = 1
Const $ODS_SELECTED = 0x0001
Const $ODS_DISABLED = 0x0004

_Example()

Func _Example()
    ; Create global brushes
    $g_hBrushEdit = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_EDIT_BG))
    $g_hBrushButton = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BUTTON_BG))
    $g_hBrushBg = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK))

    #Region GUI
    $g_hGUI = GUICreate("Sample GUI with Dark Mode", 400, 400)
    GUISetIcon(@SystemDir & "\mspaint.exe", 0)
    GUISetBkColor($COLOR_BG_DARK, $g_hGUI)

    ; Register GUI-level WM_CTLCOLOR messages
    GUIRegisterMsg($WM_CTLCOLOREDIT, "_WM_CTLCOLOR")
    GUIRegisterMsg($WM_CTLCOLORLISTBOX, "_WM_CTLCOLOR")
    GUIRegisterMsg($WM_CTLCOLORBTN, "_WM_CTLCOLOR")
    GUIRegisterMsg($WM_CTLCOLORSTATIC, "_WM_CTLCOLOR")
    GUIRegisterMsg($WM_INITMENUPOPUP, "_OnInitMenuPopup")
    GUIRegisterMsg($WM_MEASUREITEM, "WM_MEASUREITEM_Handler")
    GUIRegisterMsg($WM_DRAWITEM,    "WM_DRAWITEM_Handler")
    GUIRegisterMsg($WM_ACTIVATE, "_WM_ACTIVATE_OverpaintLine")
    GUIRegisterMsg($WM_WINDOWPOSCHANGED, "_WM_WINDOWPOSCHANGED_OverpaintLine")
    #EndRegion GUI

    #Region MENU
    Global $g_aMenuText[4]
    $g_aMenuText[0] = "Menu &One"
    $g_aMenuText[1] = "Menu &Two"
    $g_aMenuText[2] = "Menu Th&ree"
    $g_aMenuText[3] = "Menu &Four"

    Local $idMenu1 = GUICtrlCreateMenu($g_aMenuText[0])
    Local $idMenu2 = GUICtrlCreateMenu($g_aMenuText[1])
    GUICtrlCreateMenu($g_aMenuText[2])
    GUICtrlCreateMenu($g_aMenuText[3])
    GUICtrlCreateMenuItem('SubMenu One &A', $idMenu1)
    GUICtrlCreateMenuItem('SubMenu One &B', $idMenu1)

    ; Owner-draw Top-Level Menu einrichten
    _MakeMenuOwnerDraw($g_hGUI)

    #EndRegion MENU

    #Region CONTEXT MENU
    Local $idContextMenu = GUICtrlCreateContextMenu()
    GUICtrlCreateMenuItem("Context Menu", $idContextMenu)
    GUICtrlCreateMenuItem("", $idContextMenu)
    GUICtrlCreateMenuItem("&Properties", $idContextMenu)
    #EndRegion CONTEXT MENU

    #Region PIC
    Local $idPic = GUICtrlCreatePic("", 0, 0, 169, 68)
    GUICtrlSetImage($idPic, "C:\Program Files (x86)\AutoIt3\Examples\GUI\logo4.gif")
    GUICtrlSetTip(-1, '#Region PIC')
    $g_idLabelPic = GUICtrlCreateLabel("Sample Pic", 75, 1, 53, 15)
    $g_hLabelPic = GUICtrlGetHandle($g_idLabelPic)
    #EndRegion PIC

    #Region AVI
    Local $idAvi = GUICtrlCreateAvi("C:\Program Files (x86)\AutoIt3\Examples\GUI\SampleAVI.avi", 0, 180, 10, 32, 32, $ACS_AUTOPLAY)
    GUICtrlSetTip(-1, '#Region AVI')
    GUICtrlCreateLabel("Sample avi", 175, 50)
    #EndRegion AVI

    #Region TAB
    Local $idTab = GUICtrlCreateTab(240, 0, 150, 70), $g_hTab = GUICtrlGetHandle($idTab)
    _AddControlForSubclass($idTab)
    GUICtrlCreateTabItem("One")
    GUICtrlSetTip(-1, '#Region TAB1')
    GUICtrlCreateLabel("Sample Tab", 250, 40)
    GUICtrlCreateTabItem("Two")
    GUICtrlSetTip(-1, '#Region TAB2')
    GUICtrlCreateTabItem("Three")
    GUICtrlSetTip(-1, '#Region TAB3')
    GUICtrlCreateTabItem("")
    $g_hTab = GUICtrlGetHandle($idTab)
    #EndRegion TAB

    #Region COMBO
    Local $idCombo = GUICtrlCreateCombo("Sample Combo", 250, 80, 120, 100)
    GUICtrlSetData($idCombo, "Item 2|Item 3", "Sample Combo")
    _AddControlForSubclass($idCombo)
    GUICtrlSetTip(-1, '#Region COMBO')
    #EndRegion COMBO

    #Region PROGRESS
    Local $idProgress = GUICtrlCreateProgress(60, 80, 150, 20)
    _AddControlForSubclass($idProgress)
    GUICtrlSetTip(-1, '#Region PROGRESS')
    GUICtrlSetData(-1, 60)
    GUICtrlCreateLabel("Progress:", 5, 82)
    #EndRegion PROGRESS

    #Region EDIT
    Local $idEdit = GUICtrlCreateEdit(@CRLF & "  Sample Edit Control", 10, 110, 150, 70)
    _AddControlForSubclass($idEdit)
    GUICtrlSetTip(-1, '#Region EDIT')
    #EndRegion EDIT

    #Region LIST
    Local $idList = GUICtrlCreateList("", 5, 190, 100, 90)
    _AddControlForSubclass($idList)
    GUICtrlSetTip(-1, '#Region LIST')
    GUICtrlSetData(-1, "A.Sample|B.List|C.Control|D.Here", "B.List")
    #EndRegion LIST

    #Region ICON
    GUICtrlCreateIcon("explorer.exe", 0, 175, 120)
    GUICtrlSetTip(-1, '#Region ICON')
    GUICtrlCreateLabel("Icon", 180, 160, 50, 20)
    #EndRegion ICON

    #Region LIST VIEW
    Local $idListView = GUICtrlCreateListView("Sample|ListView|", 110, 190, 110, 80, $LVS_REPORT)
    _AddControlForSubclass($idListView)
    GUICtrlSetBkColor($idListView, $COLOR_EDIT_BG)
    GUICtrlSetColor($idListView, $COLOR_TEXT_LIGHT)
    GUICtrlSetTip(-1, '#Region LIST VIEW')
    GUICtrlCreateListViewItem("A|One", $idListView)
    GUICtrlCreateListViewItem("B|Two", $idListView)
    GUICtrlCreateListViewItem("C|Three", $idListView)
    $g_ListView = GUICtrlGetHandle($idListView)
    #EndRegion LIST VIEW

    #Region GROUP WITH RADIO BUTTONS
    Local $idGroup = GUICtrlCreateGroup("Sample Group", 230, 120)
    GUICtrlSetColor($idGroup, $COLOR_TEXT_LIGHT)
    Local $idRadio1 = GUICtrlCreateRadio("Radio One", 250, 140, 80)
    GUICtrlSetTip($idRadio1, '#Region RADIO1')
    GUICtrlSetState($idRadio1, $GUI_CHECKED)
    Local $idRadio2 = GUICtrlCreateRadio("Radio Two", 250, 165, 80)
    GUICtrlSetTip($idRadio2, '#Region RADIO2')
    GUICtrlCreateGroup("", -99, -99, 1, 1)
    DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idGroup), "wstr", 0, "wstr", 0)
    DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idRadio1), "wstr", 0, "wstr", 0)
    DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idRadio2), "wstr", 0, "wstr", 0)
    #EndRegion GROUP WITH RADIO BUTTONS

    #Region UPDOWN
    GUICtrlCreateLabel("UpDown", 350, 115)
    GUICtrlSetColor(-1, $COLOR_TEXT_LIGHT)
    Local $idInput = GUICtrlCreateInput("42", 350, 130, 40, 20)
    _AddControlForSubclass($idInput)
    Local $idUpDown = GUICtrlCreateUpdown(-1)
    _AddControlForSubclass($idUpDown)
    #EndRegion UPDOWN

    #Region LABEL
    $g_idLabelGreen = GUICtrlCreateLabel("Green" & @CRLF & "Label", 350, 165, 40, 40)
    $g_hLabelGreen = GUICtrlGetHandle($g_idLabelGreen)
    GUICtrlSetTip($g_idLabelGreen, '#Region LABEL')
    $g_hBrushGreen = _WinAPI_CreateSolidBrush(_ColorToCOLORREF(0x00FF00)) ; green background

    #Region SLIDER
    GUICtrlCreateLabel("Slider:", 235, 215)
    Local $idSlider = GUICtrlCreateSlider(270, 210, 120, 30)
    _AddControlForSubclass($idSlider)
    GUICtrlSetTip(-1, '#Region SLIDER')
    GUICtrlSetData(-1, 30)
    #EndRegion SLIDER

    #Region INPUT
    Local $idInput2 = GUICtrlCreateInput("Sample Input Box", 235, 255, 130, 20)
    _AddControlForSubclass($idInput2)
    GUICtrlSetTip(-1, '#Region INPUT')
    #EndRegion INPUT

    #Region DATE
    Local $idDate = GUICtrlCreateDate("", 5, 280, 200, 20)
    _AddControlForSubclass($idDate)
    GUICtrlSetBkColor($idDate, $COLOR_EDIT_BG)
    GUICtrlSetColor($idDate, $COLOR_TEXT_LIGHT)
    GUICtrlSetTip(-1, '#Region DATE')
    GUICtrlCreateLabel("(Date control expands into a calendar)", 10, 305, 200, 20)
    GUICtrlSetColor(-1, $COLOR_TEXT_LIGHT)
    #EndRegion DATE

    #Region BUTTON
    Local $idButton = GUICtrlCreateButton("Sample Button", 10, 330, 100, 30)
    _AddControlForSubclass($idButton)
    GUICtrlSetTip(-1, '#Region BUTTON')
    #EndRegion BUTTON

    #Region CHECKBOX
    Local $idCheckBox = GUICtrlCreateCheckbox("Checkbox", 130, 335, 80, 20)
    GUICtrlSetTip(-1, '#Region CHECKBOX')
    DllCall("UxTheme.dll", "int", "SetWindowTheme", "hwnd", GUICtrlGetHandle($idCheckBox), "wstr", 0, "wstr", 0)
    #EndRegion CHECKBOX

    #Region TREEVIEW ONE
    Local $idTreeView1 = GUICtrlCreateTreeView(210, 290, 80, 80)
    _AddControlForSubclass($idTreeView1)
    GUICtrlSetBkColor($idTreeView1, $COLOR_EDIT_BG)
    GUICtrlSetColor($idTreeView1, $COLOR_TEXT_LIGHT)
    GUICtrlSetTip(-1, '#Region TREEVIEW ONE')
    Local $idTreeViewItem = GUICtrlCreateTreeViewItem("TreeView", $idTreeView1)
    GUICtrlCreateTreeViewItem("Item1", $idTreeViewItem)
    GUICtrlCreateTreeViewItem("Item2", $idTreeViewItem)
    GUICtrlCreateTreeViewItem("Foo", -1)
    GUICtrlSetState($idTreeViewItem, $GUI_EXPAND)
    #EndRegion TREEVIEW ONE

    #Region TREEVIEW TWO
    Local $idTreeView2 = GUICtrlCreateTreeView(295, 290, 103, 80, $TVS_CHECKBOXES)
    _AddControlForSubclass($idTreeView2)
    GUICtrlSetBkColor($idTreeView2, $COLOR_EDIT_BG)
    GUICtrlSetColor($idTreeView2, $COLOR_TEXT_LIGHT)
    GUICtrlSetTip(-1, '#Region TREEVIEW TWO')
    GUICtrlCreateTreeViewItem("TreeView", $idTreeView2)
    GUICtrlCreateTreeViewItem("With", $idTreeView2)
    GUICtrlCreateTreeViewItem("$TVS_CHECKBOXES", $idTreeView2)
    GUICtrlSetState(-1, $GUI_CHECKED)
    GUICtrlCreateTreeViewItem("Style", $idTreeView2)
    #EndRegion TREEVIEW TWO

    ; Apply Dark Mode
    _ApplyDarkModeToAllControls()

    ; Handle scrollbars for windows that have them
    _EnableDarkScrollBars()

    ; Register a custom window procedure for the tab control for owner-drawing
    $g_hTab_CB = DllCallbackRegister('_WinProc', 'ptr', 'hwnd;uint;wparam;lparam')
    $g_pTab_CB = DllCallbackGetPtr($g_hTab_CB)
    $g_hProc = _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_pTab_CB)

    GUISetState(@SW_SHOW)

    _OverpaintWhiteLine()
    _WinAPI_RedrawWindow($g_hGUI, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW))

    While 1
        Switch GUIGetMsg()
            Case $GUI_EVENT_CLOSE
                _CleanupSubclassing()
                _CleanupBrushes()
                ExitLoop
        EndSwitch
    WEnd
    ; Restore the original window procedure for the tab control
    _WinAPI_SetWindowLong($g_hTab, $GWL_WNDPROC, $g_hProc)
    DllCallbackFree($g_hTab_CB)

    GUIDelete()
EndFunc   ;==>_Example

Func _OverpaintWhiteLine() ;under menu bar
    Local $hDC = _WinAPI_GetWindowDC($g_hGUI)
    If Not $hDC Then Return

    Local $tWndRect = _WinAPI_GetWindowRect($g_hGUI)
    Local $iWndWidth = $tWndRect.right - $tWndRect.left

    ; Übermale die weiße Linie bei Y=45
    Local $tRect = DllStructCreate($tagRECT)
    With $tRect
        .left = 0
        .top = 45
        .right = $iWndWidth
        .bottom = 46
    EndWith

    Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK))
    _WinAPI_FillRect($hDC, $tRect, $hBrush)
    _WinAPI_DeleteObject($hBrush)

    _WinAPI_ReleaseDC($g_hGUI, $hDC)
EndFunc   ;==>_OverpaintWhiteLine

Func _WM_ACTIVATE_OverpaintLine($hWnd, $iMsg, $wParam, $lParam)
    If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG
    _OverpaintWhiteLine()
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_ACTIVATE_OverpaintLine

Func _WM_WINDOWPOSCHANGED_OverpaintLine($hWnd, $iMsg, $wParam, $lParam)
    If $hWnd <> $g_hGUI Then Return $GUI_RUNDEFMSG
    _OverpaintWhiteLine()
    Return $GUI_RUNDEFMSG
EndFunc   ;==>_WM_WINDOWPOSCHANGED_OverpaintLine

Func _OnInitMenuPopup($hWnd, $iMsg, $wParam, $lParam)
    ; wParam = HMENU of the popup, lParam = position/index - not needed here
    ; A small delay sometimes helps to ensure the popup window exists
    Sleep(100)

    ; The foreground window is most likely the new menu popup
    Local $hPopup = _WinAPI_GetForegroundWindow()
    If Not $hPopup Then Return $GUI_RUNDEFMSG

    Local $sCls = StringLower(_WinAPI_GetClassName($hPopup))
    If $sCls <> "#32768" And $sCls <> "popupmenu" Then
        ; if no menu popup is detected -> do nothing
        Return $GUI_RUNDEFMSG
    EndIf

    ; Set Theme + AllowDarkMode on the popup itself
    _WinAPI_SetWindowTheme($hPopup, "DarkMode_Explorer", "")
    _WinAPI_AllowDarkModeForWindow($hPopup, True)

    ; Also apply the theme to all child windows of the popup (e.g., scrollbars)
    Local $hChild = _WinAPI_GetWindow($hPopup, $GW_CHILD)
    While $hChild
        Local $sChildCls = StringLower(_WinAPI_GetClassName($hChild))
        ; apply theme specifically for scrollbars, UpDown, etc.
        If $sChildCls = "scrollbar" Or $sChildCls = "msctls_updown32" Or $sChildCls = "traynotifywnd" Then
            _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "")
            _WinAPI_AllowDarkModeForWindow($hChild, True)
        Else
            ; try generically
            _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", "")
            _WinAPI_AllowDarkModeForWindow($hChild, True)
        EndIf
        $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT)
    WEnd

    ; Force refresh so the change is visible immediately
    _WinAPI_FlushMenuThemes()
    _WinAPI_RefreshImmersiveColorPolicyState()
    _WinAPI_RedrawWindow($hPopup, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW))

    Return $GUI_RUNDEFMSG
EndFunc   ;==>_OnInitMenuPopup

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

Func _AddControlForSubclass($iCtrlID)
    Local $hCtrl = GUICtrlGetHandle($iCtrlID)
    If $hCtrl Then
        $g_aControls[$g_iControlCount][0] = $iCtrlID
        $g_aControls[$g_iControlCount][1] = $hCtrl
        $g_aControls[$g_iControlCount][2] = 0 ; Placeholder for OldWndProc
        $g_iControlCount += 1
    EndIf
EndFunc   ;==>_AddControlForSubclass

Func _ApplyDarkModeToAllControls()
    ; DWM Dark Mode for the main window
    _WinAPI_SetPreferredAppMode($APPMODE_FORCEDARK)

    ; Create subclass callback
    If Not $g_pSubclassProc Then
        $g_pSubclassProc = DllCallbackRegister("_SubclassProc", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")
    EndIf

    ; Subclass all controls
    For $i = 0 To $g_iControlCount - 1
        Local $hCtrl = $g_aControls[$i][1]
        If $hCtrl Then
            Local $sClass = _WinAPI_GetClassName($hCtrl)
            ; Use SetWindowSubclass
            _WinAPI_SetWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i, 0)

            ; Special themes for different control types
            Switch StringLower($sClass)
                Case "edit", "richedit", "richedit20a", "richedit20w"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0)
                Case "button"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "combobox"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_CFD", 0)
                    ; Handle ComboBox child-edit
                    Local $hEdit = _WinAPI_FindWindowEx($hCtrl, 0, "Edit", "")
                    If $hEdit Then
                        _WinAPI_SetWindowTheme($hEdit, "DarkMode_CFD", 0)
                        _WinAPI_AllowDarkModeForWindow($hEdit, True)
                    EndIf
                    ; ComboBox dropdown list
                    Local $hComboLBox = _WinAPI_FindWindowEx($hCtrl, 0, "ComboLBox", "")
                    If $hComboLBox Then
                        _WinAPI_SetWindowTheme($hComboLBox, "DarkMode_Explorer", 0)
                        _WinAPI_AllowDarkModeForWindow($hComboLBox, True)
                    EndIf
                Case "syslistview32"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                    ; ListView extended styles for better dark mode
                    _SendMessage($hCtrl, $LVS_EX_DOUBLEBUFFER, 0x00010000, 0x00010000)
                    ; Also make the ListView header dark
                    Local $hHeader = _SendMessage($hCtrl, $LVM_GETHEADER, 0, 0)
                    If $hHeader Then
                        _WinAPI_SetWindowTheme($hHeader, "DarkMode_ItemsView", 0)
                    EndIf
                Case "systreeview32"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "msctls_trackbar32" ; Slider
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "systabcontrol32"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", "") ;must be ""
                    ; tab-Control background
                    _SendMessage($hCtrl, 0x132D, 0, $COLOR_BG_DARK) ; TCM_SETBKCOLOR
                    ; Try to make the UpDown (spinner for too many tabs) dark as well
                    Local $hUpDown = _WinAPI_FindWindowEx($hCtrl, 0, "msctls_updown32", "")
                    If $hUpDown Then _WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer", 0)
                Case "listbox"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "msctls_progress32"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "scrollbar"
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                Case "sysdatetimepick32"
                    ; Parent DTP dark theme
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
                    _WinAPI_AllowDarkModeForWindow($hCtrl, True)

                    ; Child Edit (the visible text part)
                    Local $hEditChild = _WinAPI_FindWindowEx($hCtrl, 0, "Edit", "")
                    If $hEditChild Then
                        _WinAPI_SetWindowTheme($hEditChild, "DarkMode_CFD", 0)
                        _WinAPI_AllowDarkModeForWindow($hEditChild, True)
                    EndIf

                    ; UpDown / Spinner
                    Local $hUpDown = _WinAPI_FindWindowEx($hCtrl, 0, "msctls_updown32", "")
                    If $hUpDown Then
                        _WinAPI_SetWindowTheme($hUpDown, "DarkMode_Explorer", 0)
                        _WinAPI_AllowDarkModeForWindow($hUpDown, True)
                    EndIf
                Case Else
                    _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
            EndSwitch

            _WinAPI_AllowDarkModeForWindow($hCtrl, True)
        EndIf
    Next

    ; Update theme system
    _WinAPI_RefreshImmersiveColorPolicyState()
    _WinAPI_FlushMenuThemes()
    _WinAPI_DwmSetWindowAttribute($g_hGUI, $DWMWA_USE_IMMERSIVE_DARK_MODE, True)


    ; Redraw GUI
    _WinAPI_RedrawWindow($g_hGUI, 0, 0, $RDW_UPDATENOW)
EndFunc   ;==>_ApplyDarkModeToAllControls

Func _CleanupSubclassing()
    ; Remove all subclasses
    If $g_pSubclassProc Then
        For $i = 0 To $g_iControlCount - 1
            Local $hCtrl = $g_aControls[$i][1]
            If $hCtrl Then
                _WinAPI_RemoveWindowSubclass($hCtrl, DllCallbackGetPtr($g_pSubclassProc), $i)
            EndIf
        Next
        DllCallbackFree($g_pSubclassProc)
        $g_pSubclassProc = 0
    EndIf
EndFunc   ;==>_CleanupSubclassing

Func _SubclassProc($hWnd, $iMsg, $wParam, $lParam, $iID, $pData)
    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   ;==>_SubclassProc

Func _MakeMenuOwnerDraw($hWnd)
    ; Get menu handle
    $g_hMenu = _GUICtrlMenu_GetMenu($hWnd)
    If Not $g_hMenu Then Return False

    Local $iCount = _GUICtrlMenu_GetItemCount($g_hMenu)
    If $iCount <= 0 Then Return False

    ReDim $g_aMenuText[$iCount]

    For $i = 0 To $iCount - 1
        ; retrieve text via GetMenuStringW (works better than _GUICtrlMenu_GetItemText)
        Local $tText = DllStructCreate("wchar s[256]")
        Local $iLen = DllCall("user32.dll", "int", "GetMenuStringW", _
                                                    "handle", $g_hMenu, _
                                                    "uint", $i, _
                                                    "struct*", $tText, _
                                                    "int", 255, _
                                                    "uint", 0x0400) ; MF_BYPOSITION

        If IsArray($iLen) And $iLen[0] > 0 Then
            $g_aMenuText[$i] = $tText.s
        Else
            $g_aMenuText[$i] = ""
        EndIf

        ; set top-level item to owner-draw
        _GUICtrlMenu_SetItemType($g_hMenu, $i, $MFT_OWNERDRAW, True)
    Next

    ; redraw menu bar immediately
    _GUICtrlMenu_DrawMenuBar($hWnd)
    _WinAPI_RedrawWindow($hWnd, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW))

    Return True
EndFunc   ;==>_MakeMenuOwnerDraw

Func WM_MEASUREITEM_Handler($hWnd, $iMsg, $wParam, $lParam)
    Local $tagMEASUREITEM = "uint CtlType;uint CtlID;uint itemID;uint itemWidth;uint itemHeight;ulong_ptr itemData"
    Local $t = DllStructCreate($tagMEASUREITEM, $lParam)
    If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG

    If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG

    Local $itemID = $t.itemID

    ; itemID is the control ID, not the position!
    ; We must derive the position from the itemID
    Local $iPos = -1
    For $i = 0 To UBound($g_aMenuText) - 1
        If $itemID = ($i + 3) Then ; Offset of 3 due to internal IDs
            $iPos = $i
            ExitLoop
        EndIf
    Next

    ; Fallback: try the itemID directly
    If $iPos < 0 Then $iPos = $itemID
    If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0

    Local $sText = $g_aMenuText[$iPos]

    ; Calculate text dimensions
    Local $hDC = _WinAPI_GetDC($hWnd)
    Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0)
    If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT)
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)

    Local $tSize = _WinAPI_GetTextExtentPoint32($hDC, $sText)
    Local $iTextWidth = $tSize.X
    Local $iTextHeight = $tSize.Y

    _WinAPI_SelectObject($hDC, $hOldFont)
    _WinAPI_ReleaseDC($hWnd, $hDC)

    ; Set dimensions with padding
    $t.itemWidth = $iTextWidth + 1
    $t.itemHeight = $iTextHeight + 1

    Return 1
EndFunc   ;==>WM_MEASUREITEM_Handler

Func WM_DRAWITEM_Handler($hWnd, $iMsg, $wParam, $lParam)
    Local $tagDRAWITEM = "uint CtlType;uint CtlID;uint itemID;uint itemAction;uint itemState;ptr hwndItem;handle hDC;" & _
                         "long left;long top;long right;long bottom;ulong_ptr itemData"
    Local $t = DllStructCreate($tagDRAWITEM, $lParam)
    If Not IsDllStruct($t) Then Return $GUI_RUNDEFMSG

    If $t.CtlType <> $ODT_MENU Then Return $GUI_RUNDEFMSG

    Local $hDC     = $t.hDC
    Local $left    = $t.left
    Local $top     = $t.top
    Local $right   = $t.right
    Local $bottom  = $t.bottom
    Local $state   = $t.itemState
    Local $itemID  = $t.itemID

    ; convert itemID to position
    Local $iPos = -1
    For $i = 0 To UBound($g_aMenuText) - 1
        If $itemID = ($i + 3) Then
            $iPos = $i
            ExitLoop
        EndIf
    Next

    If $iPos < 0 Then $iPos = $itemID
    If $iPos < 0 Or $iPos >= UBound($g_aMenuText) Then $iPos = 0

    Local $sText = $g_aMenuText[$iPos]
    $sText = StringReplace($sText, "&", "")

    ; Colors
    Local $clrBG   = _ColorToCOLORREF($COLOR_BG_DARK)
    Local $clrSel  = _ColorToCOLORREF(0x505050)
    Local $clrText = _ColorToCOLORREF($COLOR_TEXT_LIGHT)

    Static $iDrawCount = 0
    Static $bFullBarDrawn = False

    ; Count how many items were drawn in this "draw cycle"
    $iDrawCount += 1

    ; If we are at the first item AND the bar has not yet been drawn
    If $iPos = 0 And Not $bFullBarDrawn Then
        ; Get the full window width
        Local $tClient = _WinAPI_GetClientRect($hWnd)
        Local $iFullWidth = DllStructGetData($tClient, "right")

        ; Fill the entire menu bar
        Local $tFullMenuBar = DllStructCreate($tagRECT)
        With $tFullMenuBar
            .left = 0
            .top = $top
            .right =  $iFullWidth + 3
            .bottom = $bottom
        EndWith

        Local $hFullBrush = _WinAPI_CreateSolidBrush($clrBG)
        _WinAPI_FillRect($hDC, $tFullMenuBar, $hFullBrush)
        _WinAPI_DeleteObject($hFullBrush)
    EndIf

    ; After drawing all items, mark as "drawn"
    If $iDrawCount >= UBound($g_aMenuText) Then
        $bFullBarDrawn = True
        $iDrawCount = 0
    EndIf

    ; Draw background for the area AFTER the last menu item
    If $iPos = (UBound($g_aMenuText) - 1) Then ; Last menu
        Local $tClient = _WinAPI_GetClientRect($hWnd)
        Local $iFullWidth = DllStructGetData($tClient, "right")

        ; Fill only the area to the RIGHT of the last menu item
        If $right < $iFullWidth Then
            Local $tEmptyArea = DllStructCreate($tagRECT)
            With $tEmptyArea
                .left = $right
                .top = $top
                .right = $iFullWidth + _WinAPI_GetSystemMetrics(7)
                .bottom = $bottom
            EndWith

            Local $hEmptyBrush = _WinAPI_CreateSolidBrush($clrBG)
            _WinAPI_FillRect($hDC, $tEmptyArea, $hEmptyBrush)
            _WinAPI_DeleteObject($hEmptyBrush)
        EndIf
    EndIf

    ; Draw item background (selected = lighter)
    Local $bSelected = BitAND($state, $ODS_SELECTED)
    Local $hBrush = _WinAPI_CreateSolidBrush($bSelected ? $clrSel : $clrBG)

    Local $tItemRect = DllStructCreate($tagRECT)
    With $tItemRect
        .left = $left
        .top = $top
        .right = $right
        .bottom = $bottom
    EndWith

    _WinAPI_FillRect($hDC, $tItemRect, $hBrush)
    _WinAPI_DeleteObject($hBrush)

    ; Setup font
    Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0)
    If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT)
    Local $hOldFont = _WinAPI_SelectObject($hDC, $hFont)

    _WinAPI_SetBkMode($hDC, $TRANSPARENT)
    _WinAPI_SetTextColor($hDC, $clrText)

    ; Draw text
    Local $tTextRect = DllStructCreate($tagRECT)
    With $tTextRect
        .left = $left + 10
        .top = $top + 4
        .right = $right - 10
        .bottom = $bottom - 4
    EndWith

    DllCall("user32.dll", "int", "DrawTextW", "handle", $hDC, "wstr", $sText, "int", -1, "ptr", DllStructGetPtr($tTextRect), "uint", BitOR($DT_SINGLELINE, $DT_VCENTER, $DT_LEFT))

    If $hOldFont Then _WinAPI_SelectObject($hDC, $hOldFont)

    Return 1
EndFunc   ;==>WM_DRAWITEM_Handler

Func _WM_CTLCOLOR($hWnd, $iMsg, $wParam, $lParam)
    Local $hDC = $wParam
    Local $hCtrl = $lParam

    ; If the control is the special green label -> return green background
    If $hCtrl = $g_hLabelGreen Then
        ; black text on a green background
        _WinAPI_SetTextColor($hDC, _ColorToCOLORREF(0x000000))
        _WinAPI_SetBkColor($hDC, _ColorToCOLORREF(0x00FF00))
        _WinAPI_SetBkMode($hDC, $OPAQUE) ; important, otherwise it remains transparent and you cannot see the background
        If $g_hBrushGreen Then Return $g_hBrushGreen
    EndIf

    ; --- Special case: Make "Sample Pic" label transparent ---
    If $hCtrl = $g_hLabelPic Then
        ; set transparent background
        _WinAPI_SetBkMode($hDC, $TRANSPARENT)
        ; set text color (if necessary) - e.g., white
        _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT))
        ; return NULL_BRUSH (stock object), so Windows does NOT fill with your dark brush
        Local $hNull = _WinAPI_GetStockObject(5) ; 5 = NULL_BRUSH
        If $hNull Then Return $hNull
        ; Fallback if not available:
        Return $GUI_RUNDEFMSG
    EndIf

    ; --- Default behavior for all other statics / controls ---
    _WinAPI_SetTextColor($hDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT))

    Local $hBrush = $g_hBrushEdit
    Local $iColor = $COLOR_EDIT_BG

    Switch $iMsg
        Case $WM_CTLCOLORBTN
            $hBrush = $g_hBrushButton
            $iColor = $COLOR_BUTTON_BG
        Case $WM_CTLCOLORSTATIC
            $hBrush = $g_hBrushBg
            $iColor = $COLOR_BG_DARK
    EndSwitch
    _WinAPI_SetBkColor($hDC, _ColorToCOLORREF($iColor))
    _WinAPI_SetBkMode($hDC, $TRANSPARENT)

    Return $hBrush
EndFunc   ;==>_WM_CTLCOLOR

Func _CleanupBrushes()
    ; Delete all brushes
    If $g_hBrushEdit Then _WinAPI_DeleteObject($g_hBrushEdit)
    If $g_hBrushButton Then _WinAPI_DeleteObject($g_hBrushButton)
    If $g_hBrushBg Then _WinAPI_DeleteObject($g_hBrushBg)
    If $g_hBrushGreen Then _WinAPI_DeleteObject($g_hBrushGreen)
EndFunc   ;==>_CleanupBrushes

Func _EnableDarkScrollBars()
    ; Try to enable Dark Mode for all scrollbars (also for TreeView with checkboxes)
    For $i = 0 To $g_iControlCount - 1
        Local $hCtrl = $g_aControls[$i][1]
        If Not $hCtrl Then ContinueLoop

        ; 1️ Normal attempt (works for most controls)
        Local $tScrollInfo = _GUIScrollBars_GetScrollInfoEx($hCtrl, 1)
        If IsDllStruct($tScrollInfo) Then
            _WinAPI_SetWindowTheme($hCtrl, "DarkMode_Explorer", 0)
        EndIf

        ; 2️ Extension: If the control has its own scrollbar child windows (e.g., TreeView with $TVS_CHECKBOXES)
        Local $hChild = _WinAPI_GetWindow($hCtrl, $GW_CHILD)
        While $hChild
            Local $sClass = _WinAPI_GetClassName($hChild)
            If StringCompare($sClass, "ScrollBar") = 0 Then
                ; Set DarkMode on the ScrollBar itself
                _WinAPI_SetWindowTheme($hChild, "DarkMode_Explorer", 0)
                _WinAPI_AllowDarkModeForWindow($hChild, True)
            EndIf
            $hChild = _WinAPI_GetWindow($hChild, $GW_HWNDNEXT)
        WEnd
    Next
EndFunc   ;==>_EnableDarkScrollBars

Func _WinProc($hWnd, $iMsg, $wParam, $lParam)
    ; Custom window procedure for tab control with Dark Mode
    Switch $iMsg
        Case $WM_ERASEBKGND
            Return 1 ; Prevent background erase to avoid flicker

        Case $WM_PAINT
            Local $tPaint = DllStructCreate($tagPAINTSTRUCT)
            Local $hDC = DllCall("user32.dll", "handle", "BeginPaint", "hwnd", $hWnd, "struct*", $tPaint)
            If @error Or Not $hDC[0] Then Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam)
            $hDC = $hDC[0]

            ; Get client rectangle
            Local $tClient = _WinAPI_GetClientRect($hWnd)
            If Not IsDllStruct($tClient) Then
                _WinAPI_EndPaint($hWnd, $tPaint)
                Return 0
            EndIf

            Local $iWidth = $tClient.Right
            Local $iHeight = $tClient.Bottom

            ; Create memory DC for double buffering
            Local $hMemDC = _WinAPI_CreateCompatibleDC($hDC)
            Local $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight)
            Local $hOldBmp = _WinAPI_SelectObject($hMemDC, $hBitmap)

            ; Fill background
            Local $hBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($COLOR_BG_DARK))
            _WinAPI_FillRect($hMemDC, $tClient, $hBrush)
            _WinAPI_DeleteObject($hBrush)

            ; Get tab info
            Local $iTabCount = _SendMessage($hWnd, 0x1304, 0, 0) ; TCM_GETITEMCOUNT
            Local $iCurSel = _SendMessage($hWnd, 0x130B, 0, 0)   ; TCM_GETCURSEL

            ; Setup font
            Local $hFont = _SendMessage($hWnd, $WM_GETFONT, 0, 0)
            If Not $hFont Then $hFont = _WinAPI_GetStockObject($DEFAULT_GUI_FONT)
            Local $hOldFont = _WinAPI_SelectObject($hMemDC, $hFont)

            _WinAPI_SetBkMode($hMemDC, $TRANSPARENT)
            _WinAPI_SetTextColor($hMemDC, _ColorToCOLORREF($COLOR_TEXT_LIGHT))

            ; Draw each tab
            Local $tRect, $tRect, $iLeft, $iTop, $iRight, $iBottom
            For $i = 0 To $iTabCount - 1
                ; Get tab rectangle using TCM_GETITEMRECT
                $tRect = DllStructCreate($tagRECT)
                $aResult = DllCall("user32.dll", "lresult", "SendMessageW", _
                                                            "hwnd", $hWnd, _
                                                            "uint", 0x130A, _  ; TCM_GETITEMRECT
                                                            "wparam", $i, _
                                                            "struct*", $tRect)
                If @error Or Not $aResult[0] Then ContinueLoop

                $iLeft = $tRect.Left
                $iTop = $tRect.Top
                $iRight = $tRect.Right
                $iBottom = $tRect.Bottom

                ; Skip if rectangle is invalid
                If $iLeft >= $iRight Or $iTop >= $iBottom Then ContinueLoop

                ; Get tab text
                Local $tItem = DllStructCreate("uint Mask;dword dwState;dword dwStateMask;ptr pszText;int cchTextMax;int iImage;lparam lParam")
                Local $tText = DllStructCreate("wchar Text[256]")
                With $tItem
                    .Mask = 0x0001 ; TCIF_TEXT
                    .pszText = DllStructGetPtr($tText)
                    .cchTextMax = 256
                EndWith

                DllCall("user32.dll", "lresult", "SendMessageW", _
                                                "hwnd", $hWnd, _
                                                "uint", 0x133C, _  ; TCM_GETITEMW
                                                "wparam", $i, _
                                                "struct*", $tItem)

                Local $sText = DllStructGetData($tText, "Text")

                ; Draw tab background
                Local $bSelected = ($i = $iCurSel)
                Local $iTabColor = $bSelected ? $COLOR_BUTTON_BG : $COLOR_BG_DARK
                Local $hTabBrush = _WinAPI_CreateSolidBrush(_ColorToCOLORREF($iTabColor))

                Local $tTabRect = DllStructCreate($tagRECT)
                DllStructSetData($tTabRect, "Left", $iLeft)
                DllStructSetData($tTabRect, "Top", $iTop)
                DllStructSetData($tTabRect, "Right", $iRight)
                DllStructSetData($tTabRect, "Bottom", $iBottom)

                _WinAPI_FillRect($hMemDC, $tTabRect, $hTabBrush)
                _WinAPI_DeleteObject($hTabBrush)

                ; Draw selection indicator (top border for selected tab)
                If $bSelected Then
                    Local $hPen = _WinAPI_CreatePen(0, 2, _ColorToCOLORREF(0x0078D4)) ; Blue accent
                    Local $hOldPen = _WinAPI_SelectObject($hMemDC, $hPen)
                    _WinAPI_MoveTo($hMemDC, $iLeft, $iTop)
                    _WinAPI_LineTo($hMemDC, $iRight - 2, $iTop)
                    _WinAPI_SelectObject($hMemDC, $hOldPen)
                    _WinAPI_DeleteObject($hPen)
                EndIf

                ; Draw separator between tabs
                If $i < $iTabCount - 1 Then
                    Local $hPenSep = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER))
                    Local $hOldPenSep = _WinAPI_SelectObject($hMemDC, $hPenSep)
                    _WinAPI_MoveTo($hMemDC, $iRight - 1, $iTop + 4)
                    _WinAPI_LineTo($hMemDC, $iRight - 1, $iBottom - 4)
                    _WinAPI_SelectObject($hMemDC, $hOldPenSep)
                    _WinAPI_DeleteObject($hPenSep)
                EndIf

                ; Draw text centered in tab
                Local $tTextRect = DllStructCreate($tagRECT)
                With $tTextRect
                    .Left = $iLeft + 6
                    .Top = $iTop + 3
                    .Right = $iRight - 6
                    .Bottom = $iBottom - 3
                EndWith

                DllCall("user32.dll", "int", "DrawTextW", _
                                            "handle", $hMemDC, _
                                            "wstr", $sText, _
                                            "int", -1, _
                                            "struct*", $tTextRect, _
                                            "uint", BitOR($DT_CENTER, $DT_VCENTER, $DT_SINGLELINE))
            Next

            ; Draw border around entire control
            Local $hBorderPen = _WinAPI_CreatePen(0, 1, _ColorToCOLORREF($COLOR_BORDER))
            Local $hOldBorderPen = _WinAPI_SelectObject($hMemDC, $hBorderPen)
            Local $hNullBrush = _WinAPI_GetStockObject(5) ; NULL_BRUSH
            Local $hOldBorderBrush = _WinAPI_SelectObject($hMemDC, $hNullBrush)

            DllCall("gdi32.dll", "bool", "Rectangle", _
                                        "handle", $hMemDC, _
                                        "int", 0, _
                                        "int", 0, _
                                        "int", $iWidth, _
                                        "int", $iHeight)

            _WinAPI_SelectObject($hMemDC, $hOldBorderPen)
            _WinAPI_SelectObject($hMemDC, $hOldBorderBrush)
            _WinAPI_DeleteObject($hBorderPen)

            ; Copy to screen
            _WinAPI_BitBlt($hDC, 0, 0, $iWidth, $iHeight, $hMemDC, 0, 0, $SRCCOPY)

            ; Cleanup
            _WinAPI_SelectObject($hMemDC, $hOldFont)
            _WinAPI_SelectObject($hMemDC, $hOldBmp)
            _WinAPI_DeleteObject($hBitmap)
            _WinAPI_DeleteDC($hMemDC)

            _WinAPI_EndPaint($hWnd, $tPaint)
            Return 0
    EndSwitch

    Return _WinAPI_CallWindowProc($g_hProc, $hWnd, $iMsg, $wParam, $lParam)
EndFunc   ;==>_WinProc

Func _WinAPI_FindWindowEx($hParent, $hAfter, $sClass, $sTitle = "")
    Local $ret = DllCall("user32.dll", "hwnd", "FindWindowExW", "hwnd", $hParent, "hwnd", $hAfter, "wstr", $sClass, "wstr", $sTitle)
    If @error Or Not IsArray($ret) Then Return 0
    Return $ret[0]
EndFunc   ;==>_WinAPI_FindWindowEx


#Region DarkMode API
Func _WinAPI_ShouldAppsUseDarkMode()
    Local $aResult = DllCall("UxTheme.dll", "bool", 132)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_ShouldAppsUseDarkMode

Func _WinAPI_AllowDarkModeForWindow($hWND, $bAllow = True)
    Local $aResult = DllCall("UxTheme.dll", "bool", 133, "hwnd", $hWND, "bool", $bAllow)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_AllowDarkModeForWindow

Func _WinAPI_FlushMenuThemes()
    Local $aResult = DllCall("UxTheme.dll", "none", 136)
    If @error Then Return SetError(1, 0, False)
    Return True
EndFunc   ;==>_WinAPI_FlushMenuThemes

Func _WinAPI_RefreshImmersiveColorPolicyState()
    Local $aResult = DllCall("UxTheme.dll", "none", 104)
    If @error Then Return SetError(1, 0, False)
    Return True
EndFunc   ;==>_WinAPI_RefreshImmersiveColorPolicyState

Func _WinAPI_IsDarkModeAllowedForWindow($hWND)
    Local $aResult = DllCall("UxTheme.dll", "bool", 137, "hwnd", $hWND)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_IsDarkModeAllowedForWindow

Func _WinAPI_GetIsImmersiveColorUsingHighContrast($iIMMERSIVE_HC_CACHE_MODE)
    Local $aResult = DllCall("UxTheme.dll", "bool", 106, "long", $iIMMERSIVE_HC_CACHE_MODE)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_GetIsImmersiveColorUsingHighContrast

Func _WinAPI_OpenNcThemeData($hWND, $tClassList)
    Local $aResult = DllCall("UxTheme.dll", "hwnd", 49, "hwnd", $hWND, "struct*", $tClassList)
    If @error Then Return SetError(1, 0, False)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_OpenNcThemeData

Func _WinAPI_ShouldSystemUseDarkMode()
    Local $aResult = DllCall("UxTheme.dll", "bool", 138)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_ShouldSystemUseDarkMode

Func _WinAPI_IsDarkModeAllowedForApp()
    Local $aResult = DllCall("UxTheme.dll", "bool", 139)
    If @error Then Return SetError(1, 0, False)
    Return ($aResult[0] <> 0)
EndFunc   ;==>_WinAPI_IsDarkModeAllowedForApp

Func _WinAPI_AllowDarkModeForApp($bAllow = True) ;Windows 10 Build 17763
    Return _WinAPI_SetPreferredAppMode($bAllow ? 1 : 0) ; 1 = AllowDark, 0 = Default
EndFunc   ;==>_WinAPI_AllowDarkModeForApp

Func _WinAPI_SetPreferredAppMode($iPreferredAppMode) ;Windows 10 Build 18362+
    Local $aResult = DllCall("UxTheme.dll", "long", 135, "long", $iPreferredAppMode)
    If @error Then Return SetError(1, 0, False)
    Return $aResult[0]
EndFunc   ;==>_WinAPI_SetPreferredAppMode
#EndRegion DarkMode API

 

Sample-Controls-Dark-Mode.jpgSample-Controls-o.jpg

 

Does anyone know how to switch the menu bar and date picker to dark mode?

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Posted

There is some discussion here. I am not sure how much moder menu raw is used there. What was left as I xan remeber was the white bottom line. I think them menu needs to be ownerdrawn. I do not if that is the case for all other common controls and dark mode.

Posted (edited)

@UEZ Excellent work!

 

EDIT: I just spent around an hour studying the code. The more that I read, the more my jaw dropped to the floor. Very impressive.

I may have to find an excuse to create an app that uses tabs now. I had always dreamed of dark mode tabs in AutoIt for quite a while now. 😃

I noticed one problem. I see that you've added code to paint over the white line. However, I still see the white line under the menubar.

 

EDIT2: I changed the color of the painted line so that I could see where it was ending up and get a screenshot for you.

 

image.png.b83e022422e0bc392b23c8634f87ac2b.png

 

Edited by WildByDesign

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...