mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 01:50:09 +08:00
WIP
This commit is contained in:
parent
c94803fedb
commit
8a3d7eb12a
@ -352,7 +352,7 @@ func main() {
|
|||||||
|
|
||||||
app.SetMenu(menu)
|
app.SetMenu(menu)
|
||||||
|
|
||||||
app.NewWebviewWindow()
|
app.NewWebviewWindow().SetMenu(menu)
|
||||||
|
|
||||||
err := app.Run()
|
err := app.Run()
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ func (m *windowsApp) setApplicationMenu(menu *Menu) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *windowsApp) run() error {
|
func (m *windowsApp) run() error {
|
||||||
|
|
||||||
m.setupCommonEvents()
|
m.setupCommonEvents()
|
||||||
for eventID := range m.parent.applicationEventListeners {
|
for eventID := range m.parent.applicationEventListeners {
|
||||||
m.on(eventID)
|
m.on(eventID)
|
||||||
@ -221,6 +222,33 @@ func (m *windowsApp) wndProc(hwnd w32.HWND, msg uint32, wParam, lParam uintptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch msg {
|
switch msg {
|
||||||
|
|
||||||
|
/*
|
||||||
|
case WM_UAHDRAWMENU:
|
||||||
|
{
|
||||||
|
UAHMENU* pUDM = (UAHMENU*)lParam;
|
||||||
|
RECT rc = { 0 };
|
||||||
|
|
||||||
|
// get the menubar rect
|
||||||
|
{
|
||||||
|
MENUBARINFO mbi = { sizeof(mbi) };
|
||||||
|
GetMenuBarInfo(hWnd, OBJID_MENU, 0, &mbi);
|
||||||
|
|
||||||
|
RECT rcWindow;
|
||||||
|
GetWindowRect(hWnd, &rcWindow);
|
||||||
|
|
||||||
|
// the rcBar is offset by the window rect
|
||||||
|
rc = mbi.rcBar;
|
||||||
|
OffsetRect(&rc, -rcWindow.left, -rcWindow.top);
|
||||||
|
}
|
||||||
|
|
||||||
|
FillRect(pUDM->hdc, &rc, g_brBarBackground);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case w32.WM_UAHDRAWMENU:
|
||||||
|
return w32.UAHDrawMenu(hwnd, wParam, lParam)
|
||||||
case w32.WM_SETTINGCHANGE:
|
case w32.WM_SETTINGCHANGE:
|
||||||
settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lParam)))
|
settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lParam)))
|
||||||
if settingChanged == "ImmersiveColorSet" {
|
if settingChanged == "ImmersiveColorSet" {
|
||||||
|
@ -408,6 +408,8 @@ func (w *windowsWebviewWindow) run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Process the theme
|
// Process the theme
|
||||||
|
w32.AllowDarkModeForWindow(w.hwnd, true)
|
||||||
|
|
||||||
switch options.Windows.Theme {
|
switch options.Windows.Theme {
|
||||||
case SystemDefault:
|
case SystemDefault:
|
||||||
w.updateTheme(w32.IsCurrentlyDarkMode())
|
w.updateTheme(w32.IsCurrentlyDarkMode())
|
||||||
|
@ -606,6 +606,8 @@ const (
|
|||||||
WM_MOUSELEAVE = 0x2A3
|
WM_MOUSELEAVE = 0x2A3
|
||||||
WM_CLIPBOARDUPDATE = 0x031D
|
WM_CLIPBOARDUPDATE = 0x031D
|
||||||
WM_DPICHANGED = 0x02E0
|
WM_DPICHANGED = 0x02E0
|
||||||
|
WM_UAHDRAWMENU = 0x0091
|
||||||
|
WM_UAHDRAWMENUITEM = 0x0092
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
199
v3/pkg/w32/menubar.go
Normal file
199
v3/pkg/w32/menubar.go
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
package w32
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
const (
|
||||||
|
OBJID_MENU = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
type UAHMENU struct {
|
||||||
|
Hmenu HMENU
|
||||||
|
Hdc HDC
|
||||||
|
DwFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type MENUBARINFO struct {
|
||||||
|
CbSize uint32
|
||||||
|
Bar RECT
|
||||||
|
Menu HMENU
|
||||||
|
Window HWND
|
||||||
|
BarFocused int32
|
||||||
|
Focused int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type DRAWITEMSTRUCT struct {
|
||||||
|
ControlType uint32
|
||||||
|
ControlID uint32
|
||||||
|
ItemID uint32
|
||||||
|
ItemAction uint32
|
||||||
|
ItemState uint32
|
||||||
|
HWNDItem HWND
|
||||||
|
HDC HDC
|
||||||
|
RcItem RECT
|
||||||
|
ItemData uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
type UAHDRAWMENUITEM struct {
|
||||||
|
DIS DRAWITEMSTRUCT
|
||||||
|
UM UAHMENU
|
||||||
|
UAMI UAHMENUITEM
|
||||||
|
}
|
||||||
|
|
||||||
|
type UAHMENUITEM struct {
|
||||||
|
Position int
|
||||||
|
Umim UAHMENUITEMMETRICS
|
||||||
|
Umpm UAHMENUPOPUPMETRICS
|
||||||
|
}
|
||||||
|
type UAHMENUITEMMETRICS struct {
|
||||||
|
data [32]byte // Total size of the union in bytes (4 DWORDs * 4 bytes each * 2 arrays)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UAHMENUITEMMETRICS) RgsizeBar() *[2]struct{ cx, cy uint32 } {
|
||||||
|
return (*[2]struct{ cx, cy uint32 })(unsafe.Pointer(&u.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *UAHMENUITEMMETRICS) RgsizePopup() *[4]struct{ cx, cy uint32 } {
|
||||||
|
return (*[4]struct{ cx, cy uint32 })(unsafe.Pointer(&u.data))
|
||||||
|
}
|
||||||
|
|
||||||
|
type UAHMENUPOPUPMETRICS struct {
|
||||||
|
Rgcx [4]uint32 // Array of 4 DWORDs
|
||||||
|
FUpdateMaxWidths uint32 // Bit-field represented as a uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to get the value of the fUpdateMaxWidths bit-field
|
||||||
|
func (u *UAHMENUPOPUPMETRICS) GetFUpdateMaxWidths() uint32 {
|
||||||
|
return u.FUpdateMaxWidths & 0x3 // Mask to get the first 2 bits
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to set the value of the fUpdateMaxWidths bit-field
|
||||||
|
func (u *UAHMENUPOPUPMETRICS) SetFUpdateMaxWidths(value uint32) {
|
||||||
|
u.FUpdateMaxWidths = (u.FUpdateMaxWidths &^ 0x3) | (value & 0x3) // Clear and set the first 2 bits
|
||||||
|
}
|
||||||
|
|
||||||
|
var darkModeTitleBarBrush HBRUSH
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
darkModeTitleBarBrush, _, _ = procCreateSolidBrush.Call(
|
||||||
|
uintptr(0x8080FF),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateSolidBrush(color COLORREF) HBRUSH {
|
||||||
|
ret, _, _ := procCreateSolidBrush.Call(
|
||||||
|
uintptr(color),
|
||||||
|
)
|
||||||
|
return HBRUSH(ret)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UAHDrawMenu(hwnd HWND, wParam uintptr, lParam uintptr) uintptr {
|
||||||
|
if !IsCurrentlyDarkMode() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
udm := (*UAHMENU)(unsafe.Pointer(lParam))
|
||||||
|
var rc RECT
|
||||||
|
|
||||||
|
// get the menubar rect
|
||||||
|
{
|
||||||
|
menuBarInfo, err := GetMenuBarInfo(hwnd, OBJID_MENU, 0)
|
||||||
|
if err != nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
winRect := GetWindowRect(hwnd)
|
||||||
|
|
||||||
|
// the rcBar is offset by the window rect
|
||||||
|
rc = menuBarInfo.Bar
|
||||||
|
OffsetRect(&rc, int(-winRect.Left), int(-winRect.Top))
|
||||||
|
}
|
||||||
|
|
||||||
|
FillRect(udm.Hdc, &rc, darkModeTitleBarBrush)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func UAHDrawMenuItem(hwnd HWND, wParam uintptr, lParam uintptr) uintptr {
|
||||||
|
pUDMI := (*UAHDRAWMENUITEM)(unsafe.Pointer(lParam))
|
||||||
|
|
||||||
|
var pbrBackground, pbrBorder *HBRUSH
|
||||||
|
pbrBackground = &brItemBackground
|
||||||
|
pbrBorder = &brItemBackground
|
||||||
|
|
||||||
|
// get the menu item string
|
||||||
|
menuString := make([]uint16, 256)
|
||||||
|
mii := MENUITEMINFO{
|
||||||
|
CbSize: uint32(unsafe.Sizeof(mii)),
|
||||||
|
FMask: MIIM_STRING,
|
||||||
|
DwTypeData: uintptr(unsafe.Pointer(&menuString[0])),
|
||||||
|
Cch: uint32(len(menuString) - 1),
|
||||||
|
}
|
||||||
|
GetMenuItemInfo(pUDMI.um.hmenu, pUDMI.umi.iPosition, true, &mii)
|
||||||
|
|
||||||
|
// get the item state for drawing
|
||||||
|
dwFlags := DT_CENTER | DT_SINGLELINE | DT_VCENTER
|
||||||
|
|
||||||
|
iTextStateID := 0
|
||||||
|
iBackgroundStateID := 0
|
||||||
|
switch {
|
||||||
|
case pUDMI.dis.itemState&ODS_INACTIVE != 0 || pUDMI.dis.itemState&ODS_DEFAULT != 0:
|
||||||
|
// normal display
|
||||||
|
iTextStateID = MBI_NORMAL
|
||||||
|
iBackgroundStateID = MBI_NORMAL
|
||||||
|
case pUDMI.dis.itemState&ODS_HOTLIGHT != 0:
|
||||||
|
// hot tracking
|
||||||
|
iTextStateID = MBI_HOT
|
||||||
|
iBackgroundStateID = MBI_HOT
|
||||||
|
|
||||||
|
pbrBackground = &brItemBackgroundHot
|
||||||
|
pbrBorder = &brItemBorder
|
||||||
|
case pUDMI.dis.itemState&ODS_SELECTED != 0:
|
||||||
|
// clicked
|
||||||
|
iTextStateID = MBI_PUSHED
|
||||||
|
iBackgroundStateID = MBI_PUSHED
|
||||||
|
|
||||||
|
pbrBackground = &brItemBackgroundSelected
|
||||||
|
pbrBorder = &brItemBorder
|
||||||
|
case pUDMI.dis.itemState&ODS_GRAYED != 0 || pUDMI.dis.itemState&ODS_DISABLED != 0:
|
||||||
|
// disabled / grey text
|
||||||
|
iTextStateID = MBI_DISABLED
|
||||||
|
iBackgroundStateID = MBI_DISABLED
|
||||||
|
case pUDMI.dis.itemState&ODS_NOACCEL != 0:
|
||||||
|
// hide prefix
|
||||||
|
dwFlags |= DT_HIDEPREFIX
|
||||||
|
}
|
||||||
|
|
||||||
|
if g_menuTheme == 0 {
|
||||||
|
g_menuTheme = OpenThemeData(hwnd, "Menu")
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := DTTOPTS{
|
||||||
|
DtSize: uint32(unsafe.Sizeof(opts)),
|
||||||
|
DwFlags: DTT_TEXTCOLOR,
|
||||||
|
CrText: RGB(0x00, 0x00, 0x20),
|
||||||
|
ITextState: iTextStateID,
|
||||||
|
}
|
||||||
|
if iTextStateID == MBI_DISABLED {
|
||||||
|
opts.CrText = RGB(0x40, 0x40, 0x40)
|
||||||
|
}
|
||||||
|
|
||||||
|
FillRect(pUDMI.um.hdc, &pUDMI.dis.rcItem, *pbrBackground)
|
||||||
|
FrameRect(pUDMI.um.hdc, &pUDMI.dis.rcItem, *pbrBorder)
|
||||||
|
DrawThemeTextEx(g_menuTheme, pUDMI.um.hdc, MENU_BARITEM, MBI_NORMAL, uintptr(unsafe.Pointer(&menuString[0])), mii.cch, dwFlags, &pUDMI.dis.rcItem, &opts)
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMenuBarInfo(hwnd HWND, idObject uint32, idItem uint32) (*MENUBARINFO, error) {
|
||||||
|
var mi MENUBARINFO
|
||||||
|
|
||||||
|
mi.CbSize = uint32(unsafe.Sizeof(&mi))
|
||||||
|
ret, _, err := procGetMenuBarInfo.Call(
|
||||||
|
hwnd,
|
||||||
|
uintptr(idObject),
|
||||||
|
uintptr(idItem),
|
||||||
|
uintptr(unsafe.Pointer(&mi)))
|
||||||
|
if ret == 0 {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &mi, nil
|
||||||
|
}
|
@ -3,8 +3,10 @@
|
|||||||
package w32
|
package w32
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,6 +22,148 @@ const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38
|
|||||||
const SPI_GETHIGHCONTRAST = 0x0042
|
const SPI_GETHIGHCONTRAST = 0x0042
|
||||||
const HCF_HIGHCONTRASTON = 0x00000001
|
const HCF_HIGHCONTRASTON = 0x00000001
|
||||||
|
|
||||||
|
type WINDOWCOMPOSITIONATTRIB DWORD
|
||||||
|
|
||||||
|
const (
|
||||||
|
WCA_UNDEFINED WINDOWCOMPOSITIONATTRIB = 0
|
||||||
|
WCA_NCRENDERING_ENABLED WINDOWCOMPOSITIONATTRIB = 1
|
||||||
|
WCA_NCRENDERING_POLICY WINDOWCOMPOSITIONATTRIB = 2
|
||||||
|
WCA_TRANSITIONS_FORCEDISABLED WINDOWCOMPOSITIONATTRIB = 3
|
||||||
|
WCA_ALLOW_NCPAINT WINDOWCOMPOSITIONATTRIB = 4
|
||||||
|
WCA_CAPTION_BUTTON_BOUNDS WINDOWCOMPOSITIONATTRIB = 5
|
||||||
|
WCA_NONCLIENT_RTL_LAYOUT WINDOWCOMPOSITIONATTRIB = 6
|
||||||
|
WCA_FORCE_ICONIC_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 7
|
||||||
|
WCA_EXTENDED_FRAME_BOUNDS WINDOWCOMPOSITIONATTRIB = 8
|
||||||
|
WCA_HAS_ICONIC_BITMAP WINDOWCOMPOSITIONATTRIB = 9
|
||||||
|
WCA_THEME_ATTRIBUTES WINDOWCOMPOSITIONATTRIB = 10
|
||||||
|
WCA_NCRENDERING_EXILED WINDOWCOMPOSITIONATTRIB = 11
|
||||||
|
WCA_NCADORNMENTINFO WINDOWCOMPOSITIONATTRIB = 12
|
||||||
|
WCA_EXCLUDED_FROM_LIVEPREVIEW WINDOWCOMPOSITIONATTRIB = 13
|
||||||
|
WCA_VIDEO_OVERLAY_ACTIVE WINDOWCOMPOSITIONATTRIB = 14
|
||||||
|
WCA_FORCE_ACTIVEWINDOW_APPEARANCE WINDOWCOMPOSITIONATTRIB = 15
|
||||||
|
WCA_DISALLOW_PEEK WINDOWCOMPOSITIONATTRIB = 16
|
||||||
|
WCA_CLOAK WINDOWCOMPOSITIONATTRIB = 17
|
||||||
|
WCA_CLOAKED WINDOWCOMPOSITIONATTRIB = 18
|
||||||
|
WCA_ACCENT_POLICY WINDOWCOMPOSITIONATTRIB = 19
|
||||||
|
WCA_FREEZE_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 20
|
||||||
|
WCA_EVER_UNCLOAKED WINDOWCOMPOSITIONATTRIB = 21
|
||||||
|
WCA_VISUAL_OWNER WINDOWCOMPOSITIONATTRIB = 22
|
||||||
|
WCA_HOLOGRAPHIC WINDOWCOMPOSITIONATTRIB = 23
|
||||||
|
WCA_EXCLUDED_FROM_DDA WINDOWCOMPOSITIONATTRIB = 24
|
||||||
|
WCA_PASSIVEUPDATEMODE WINDOWCOMPOSITIONATTRIB = 25
|
||||||
|
WCA_USEDARKMODECOLORS WINDOWCOMPOSITIONATTRIB = 26
|
||||||
|
WCA_CORNER_STYLE WINDOWCOMPOSITIONATTRIB = 27
|
||||||
|
WCA_PART_COLOR WINDOWCOMPOSITIONATTRIB = 28
|
||||||
|
WCA_DISABLE_MOVESIZE_FEEDBACK WINDOWCOMPOSITIONATTRIB = 29
|
||||||
|
WCA_LAST WINDOWCOMPOSITIONATTRIB = 30
|
||||||
|
)
|
||||||
|
|
||||||
|
type WINDOWCOMPOSITIONATTRIBDATA struct {
|
||||||
|
Attrib WINDOWCOMPOSITIONATTRIB
|
||||||
|
PvData unsafe.Pointer
|
||||||
|
CbData uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
uxtheme = syscall.NewLazyDLL("uxtheme.dll")
|
||||||
|
procSetWindowTheme = uxtheme.NewProc("SetWindowTheme")
|
||||||
|
procAllowDarkModeForApplication = uxtheme.NewProc("AllowDarkModeForApp")
|
||||||
|
)
|
||||||
|
|
||||||
|
type PreferredAppMode = int32
|
||||||
|
|
||||||
|
const (
|
||||||
|
PreferredAppModeDefault PreferredAppMode = iota
|
||||||
|
PreferredAppModeAllowDark
|
||||||
|
PreferredAppModeForceDark
|
||||||
|
PreferredAppModeForceLight
|
||||||
|
PreferredAppModeMax
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
AllowDarkModeForWindow func(hwnd HWND, allow bool) uintptr
|
||||||
|
SetPreferredAppMode func(mode int32) uintptr
|
||||||
|
FlushMenuThemes func()
|
||||||
|
RefreshImmersiveColorPolicyState func()
|
||||||
|
ShouldAppsUseDarkMode func() bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if IsWindowsVersionAtLeast(10, 0, 18334) {
|
||||||
|
// AllowDarkModeForWindow is only available on Windows 10+
|
||||||
|
localUXTheme, err := windows.LoadLibrary("uxtheme.dll")
|
||||||
|
if err == nil {
|
||||||
|
procAllowDarkModeForWindow, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(133))
|
||||||
|
if err == nil {
|
||||||
|
AllowDarkModeForWindow = func(hwnd HWND, allow bool) uintptr {
|
||||||
|
var allowInt int32
|
||||||
|
if allow {
|
||||||
|
allowInt = 1
|
||||||
|
}
|
||||||
|
ret, _, _ := syscall.SyscallN(procAllowDarkModeForWindow, uintptr(allowInt))
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add ShouldAppsUseDarkMode
|
||||||
|
procShouldAppsUseDarkMode, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(132))
|
||||||
|
if err == nil {
|
||||||
|
ShouldAppsUseDarkMode = func() bool {
|
||||||
|
ret, _, _ := syscall.SyscallN(procShouldAppsUseDarkMode)
|
||||||
|
return ret != 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPreferredAppMode is only available on Windows 10+
|
||||||
|
procSetPreferredAppMode, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(135))
|
||||||
|
if err == nil {
|
||||||
|
SetPreferredAppMode = func(mode int32) uintptr {
|
||||||
|
ret, _, _ := syscall.SyscallN(procSetPreferredAppMode, uintptr(mode))
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add FlushMenuThemes
|
||||||
|
procFlushMenuThemesAddr, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(136))
|
||||||
|
if err == nil {
|
||||||
|
FlushMenuThemes = func() {
|
||||||
|
syscall.SyscallN(procFlushMenuThemesAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add RefreshImmersiveColorPolicyState
|
||||||
|
procRefreshImmersiveColorPolicyStateAddr, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(104))
|
||||||
|
if err == nil {
|
||||||
|
RefreshImmersiveColorPolicyState = func() {
|
||||||
|
syscall.SyscallN(procRefreshImmersiveColorPolicyStateAddr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//procAllowDarkModeForApp, err := windows.GetProcAddressByOrdinal(localUXTheme, uintptr(137))
|
||||||
|
//if err == nil {
|
||||||
|
// procAllowDarkModeForApplication = func(hwnd HWND, allow bool) uintptr {
|
||||||
|
// var allowInt int32
|
||||||
|
// if allow {
|
||||||
|
// allowInt = 1
|
||||||
|
// }
|
||||||
|
// ret, _, _ := syscall.SyscallN(procAllowDarkModeForApp, uintptr(allowInt))
|
||||||
|
// return ret
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// Initialize dark mode
|
||||||
|
if SetPreferredAppMode != nil {
|
||||||
|
SetPreferredAppMode(PreferredAppModeAllowDark)
|
||||||
|
if RefreshImmersiveColorPolicyState != nil {
|
||||||
|
RefreshImmersiveColorPolicyState()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
windows.FreeLibrary(localUXTheme)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func dwmSetWindowAttribute(hwnd uintptr, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
|
func dwmSetWindowAttribute(hwnd uintptr, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
|
||||||
ret, _, err := procDwmSetWindowAttribute.Call(
|
ret, _, err := procDwmSetWindowAttribute.Call(
|
||||||
hwnd,
|
hwnd,
|
||||||
@ -49,6 +193,42 @@ func SupportsImmersiveDarkMode() bool {
|
|||||||
return IsWindowsVersionAtLeast(10, 0, 18985)
|
return IsWindowsVersionAtLeast(10, 0, 18985)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetMenuTheme(hwnd uintptr, useDarkMode bool) {
|
||||||
|
if !SupportsThemes() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if dark mode is supported and enabled
|
||||||
|
if useDarkMode && ShouldAppsUseDarkMode != nil && !ShouldAppsUseDarkMode() {
|
||||||
|
useDarkMode = false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the window theme
|
||||||
|
themeName := "Explorer"
|
||||||
|
if useDarkMode {
|
||||||
|
themeName = "DarkMode"
|
||||||
|
}
|
||||||
|
procSetWindowTheme.Call(HWND(hwnd), uintptr(unsafe.Pointer(windows.StringToUTF16Ptr(themeName))), 0)
|
||||||
|
|
||||||
|
// Update the theme state
|
||||||
|
if RefreshImmersiveColorPolicyState != nil {
|
||||||
|
RefreshImmersiveColorPolicyState()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush menu themes to force a refresh
|
||||||
|
if FlushMenuThemes != nil {
|
||||||
|
FlushMenuThemes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set dark mode for the window
|
||||||
|
if AllowDarkModeForWindow != nil {
|
||||||
|
AllowDarkModeForWindow(HWND(hwnd), useDarkMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force a redraw
|
||||||
|
InvalidateRect(HWND(hwnd), nil, true)
|
||||||
|
}
|
||||||
|
|
||||||
func SetTheme(hwnd uintptr, useDarkMode bool) {
|
func SetTheme(hwnd uintptr, useDarkMode bool) {
|
||||||
if SupportsThemes() {
|
if SupportsThemes() {
|
||||||
attr := DwmwaUseImmersiveDarkModeBefore20h1
|
attr := DwmwaUseImmersiveDarkModeBefore20h1
|
||||||
@ -60,6 +240,7 @@ func SetTheme(hwnd uintptr, useDarkMode bool) {
|
|||||||
winDark = 1
|
winDark = 1
|
||||||
}
|
}
|
||||||
dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
|
dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
|
||||||
|
SetMenuTheme(hwnd, useDarkMode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,48 +780,6 @@ type ACCENT_POLICY struct {
|
|||||||
AnimationId DWORD
|
AnimationId DWORD
|
||||||
}
|
}
|
||||||
|
|
||||||
type WINDOWCOMPOSITIONATTRIBDATA struct {
|
|
||||||
Attrib WINDOWCOMPOSITIONATTRIB
|
|
||||||
PvData PVOID
|
|
||||||
CbData SIZE_T
|
|
||||||
}
|
|
||||||
|
|
||||||
type WINDOWCOMPOSITIONATTRIB DWORD
|
|
||||||
|
|
||||||
const (
|
|
||||||
WCA_UNDEFINED WINDOWCOMPOSITIONATTRIB = 0
|
|
||||||
WCA_NCRENDERING_ENABLED WINDOWCOMPOSITIONATTRIB = 1
|
|
||||||
WCA_NCRENDERING_POLICY WINDOWCOMPOSITIONATTRIB = 2
|
|
||||||
WCA_TRANSITIONS_FORCEDISABLED WINDOWCOMPOSITIONATTRIB = 3
|
|
||||||
WCA_ALLOW_NCPAINT WINDOWCOMPOSITIONATTRIB = 4
|
|
||||||
WCA_CAPTION_BUTTON_BOUNDS WINDOWCOMPOSITIONATTRIB = 5
|
|
||||||
WCA_NONCLIENT_RTL_LAYOUT WINDOWCOMPOSITIONATTRIB = 6
|
|
||||||
WCA_FORCE_ICONIC_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 7
|
|
||||||
WCA_EXTENDED_FRAME_BOUNDS WINDOWCOMPOSITIONATTRIB = 8
|
|
||||||
WCA_HAS_ICONIC_BITMAP WINDOWCOMPOSITIONATTRIB = 9
|
|
||||||
WCA_THEME_ATTRIBUTES WINDOWCOMPOSITIONATTRIB = 10
|
|
||||||
WCA_NCRENDERING_EXILED WINDOWCOMPOSITIONATTRIB = 11
|
|
||||||
WCA_NCADORNMENTINFO WINDOWCOMPOSITIONATTRIB = 12
|
|
||||||
WCA_EXCLUDED_FROM_LIVEPREVIEW WINDOWCOMPOSITIONATTRIB = 13
|
|
||||||
WCA_VIDEO_OVERLAY_ACTIVE WINDOWCOMPOSITIONATTRIB = 14
|
|
||||||
WCA_FORCE_ACTIVEWINDOW_APPEARANCE WINDOWCOMPOSITIONATTRIB = 15
|
|
||||||
WCA_DISALLOW_PEEK WINDOWCOMPOSITIONATTRIB = 16
|
|
||||||
WCA_CLOAK WINDOWCOMPOSITIONATTRIB = 17
|
|
||||||
WCA_CLOAKED WINDOWCOMPOSITIONATTRIB = 18
|
|
||||||
WCA_ACCENT_POLICY WINDOWCOMPOSITIONATTRIB = 19
|
|
||||||
WCA_FREEZE_REPRESENTATION WINDOWCOMPOSITIONATTRIB = 20
|
|
||||||
WCA_EVER_UNCLOAKED WINDOWCOMPOSITIONATTRIB = 21
|
|
||||||
WCA_VISUAL_OWNER WINDOWCOMPOSITIONATTRIB = 22
|
|
||||||
WCA_HOLOGRAPHIC WINDOWCOMPOSITIONATTRIB = 23
|
|
||||||
WCA_EXCLUDED_FROM_DDA WINDOWCOMPOSITIONATTRIB = 24
|
|
||||||
WCA_PASSIVEUPDATEMODE WINDOWCOMPOSITIONATTRIB = 25
|
|
||||||
WCA_USEDARKMODECOLORS WINDOWCOMPOSITIONATTRIB = 26
|
|
||||||
WCA_CORNER_STYLE WINDOWCOMPOSITIONATTRIB = 27
|
|
||||||
WCA_PART_COLOR WINDOWCOMPOSITIONATTRIB = 28
|
|
||||||
WCA_DISABLE_MOVESIZE_FEEDBACK WINDOWCOMPOSITIONATTRIB = 29
|
|
||||||
WCA_LAST WINDOWCOMPOSITIONATTRIB = 30
|
|
||||||
)
|
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684225.aspx
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms684225.aspx
|
||||||
|
@ -177,6 +177,7 @@ var (
|
|||||||
procSetMenuItemBitmaps = moduser32.NewProc("SetMenuItemBitmaps")
|
procSetMenuItemBitmaps = moduser32.NewProc("SetMenuItemBitmaps")
|
||||||
|
|
||||||
procRedrawWindow = moduser32.NewProc("RedrawWindow")
|
procRedrawWindow = moduser32.NewProc("RedrawWindow")
|
||||||
|
procGetMenuBarInfo = moduser32.NewProc("GetMenuBarInfo")
|
||||||
|
|
||||||
mainThread HANDLE
|
mainThread HANDLE
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user