mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
Menu to follow theme
This commit is contained in:
parent
12a309c8a5
commit
c5ad7de9cf
3 changed files with 192 additions and 0 deletions
|
|
@ -336,6 +336,10 @@ func (p *Systray) updateIcon() error {
|
|||
return p.setIcon(newIcon)
|
||||
}
|
||||
|
||||
func (p *Systray) updateTheme() {
|
||||
//win32.SetTheme(p.hwnd, win32.IsCurrentlyDarkMode())
|
||||
}
|
||||
|
||||
func RegisterWindow(name string, proc win32.WindowProc) (win32.HINSTANCE, error) {
|
||||
instance, exists := windowClasses[name]
|
||||
if exists {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package win32
|
||||
|
||||
import (
|
||||
"github.com/wailsapp/wails/v2/internal/system/operatingsystem"
|
||||
"golang.org/x/sys/windows"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
|
@ -28,11 +30,79 @@ var (
|
|||
procTranslateMessage = moduser32.NewProc("TranslateMessage")
|
||||
procDispatchMessage = moduser32.NewProc("DispatchMessageW")
|
||||
procPostQuitMessage = moduser32.NewProc("PostQuitMessage")
|
||||
procSystemParametersInfo = moduser32.NewProc("SystemParametersInfoW")
|
||||
|
||||
modshell32 = syscall.NewLazyDLL("shell32.dll")
|
||||
procShellNotifyIcon = modshell32.NewProc("Shell_NotifyIconW")
|
||||
|
||||
moddwmapi = syscall.NewLazyDLL("dwmapi.dll")
|
||||
procDwmSetWindowAttribute = moddwmapi.NewProc("DwmSetWindowAttribute")
|
||||
|
||||
moduxtheme = syscall.NewLazyDLL("uxtheme.dll")
|
||||
procSetWindowTheme = moduxtheme.NewProc("SetWindowTheme")
|
||||
|
||||
AllowDarkModeForWindow func(HWND, bool) uintptr
|
||||
SetPreferredAppMode func(int32) uintptr
|
||||
)
|
||||
|
||||
type PreferredAppMode = int32
|
||||
|
||||
const (
|
||||
PreferredAppModeDefault PreferredAppMode = iota
|
||||
PreferredAppModeAllowDark
|
||||
PreferredAppModeForceDark
|
||||
PreferredAppModeForceLight
|
||||
PreferredAppModeMax
|
||||
)
|
||||
|
||||
/*
|
||||
RtlGetNtVersionNumbers = void (LPDWORD major, LPDWORD minor, LPDWORD build) // 1809 17763
|
||||
ShouldAppsUseDarkMode = bool () // ordinal 132
|
||||
AllowDarkModeForWindow = bool (HWND hWnd, bool allow) // ordinal 133
|
||||
AllowDarkModeForApp = bool (bool allow) // ordinal 135, removed since 18334
|
||||
FlushMenuThemes = void () // ordinal 136
|
||||
RefreshImmersiveColorPolicyState = void () // ordinal 104
|
||||
IsDarkModeAllowedForWindow = bool (HWND hWnd) // ordinal 137
|
||||
GetIsImmersiveColorUsingHighContrast = bool (IMMERSIVE_HC_CACHE_MODE mode) // ordinal 106
|
||||
OpenNcThemeData = HTHEME (HWND hWnd, LPCWSTR pszClassList) // ordinal 49
|
||||
// Insider 18290
|
||||
ShouldSystemUseDarkMode = bool () // ordinal 138
|
||||
// Insider 18334
|
||||
SetPreferredAppMode = PreferredAppMode (PreferredAppMode appMode) // ordinal 135, since 18334
|
||||
IsDarkModeAllowedForApp = bool () // ordinal 139
|
||||
*/
|
||||
func init() {
|
||||
if IsWindowsVersionAtLeast(10, 0, 18334) {
|
||||
|
||||
// AllowDarkModeForWindow is only available on Windows 10+
|
||||
uxtheme, err := windows.LoadLibrary("uxtheme.dll")
|
||||
if err == nil {
|
||||
procAllowDarkModeForWindow, err := windows.GetProcAddressByOrdinal(uxtheme, uintptr(133))
|
||||
if err == nil {
|
||||
AllowDarkModeForWindow = func(hwnd HWND, allow bool) uintptr {
|
||||
var allowInt int32
|
||||
if allow {
|
||||
allowInt = 1
|
||||
}
|
||||
ret, _, _ := syscall.SyscallN(procAllowDarkModeForWindow, uintptr(hwnd), uintptr(allowInt))
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SetPreferredAppMode is only available on Windows 10+
|
||||
procSetPreferredAppMode, err := windows.GetProcAddressByOrdinal(uxtheme, uintptr(135))
|
||||
if err == nil {
|
||||
SetPreferredAppMode = func(mode int32) uintptr {
|
||||
ret, _, _ := syscall.SyscallN(procSetPreferredAppMode, uintptr(mode))
|
||||
return ret
|
||||
}
|
||||
SetPreferredAppMode(PreferredAppModeAllowDark)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type HANDLE uintptr
|
||||
type HINSTANCE HANDLE
|
||||
type HICON HANDLE
|
||||
|
|
@ -117,6 +187,14 @@ const (
|
|||
CS_HREDRAW = 0x0002
|
||||
)
|
||||
|
||||
var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo()
|
||||
|
||||
func IsWindowsVersionAtLeast(major, minor, buildNumber int) bool {
|
||||
return windowsVersion.Major >= major &&
|
||||
windowsVersion.Minor >= minor &&
|
||||
windowsVersion.Build >= buildNumber
|
||||
}
|
||||
|
||||
type WindowProc func(hwnd HWND, msg uint32, wparam, lparam uintptr) uintptr
|
||||
|
||||
func GetModuleHandle(value uintptr) uintptr {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,100 @@ package win32
|
|||
|
||||
import (
|
||||
"golang.org/x/sys/windows/registry"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type DWMWINDOWATTRIBUTE int32
|
||||
|
||||
const DwmwaUseImmersiveDarkModeBefore20h1 DWMWINDOWATTRIBUTE = 19
|
||||
const DwmwaUseImmersiveDarkMode DWMWINDOWATTRIBUTE = 20
|
||||
const DwmwaBorderColor DWMWINDOWATTRIBUTE = 34
|
||||
const DwmwaCaptionColor DWMWINDOWATTRIBUTE = 35
|
||||
const DwmwaTextColor DWMWINDOWATTRIBUTE = 36
|
||||
const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38
|
||||
|
||||
const SPI_GETHIGHCONTRAST = 0x0042
|
||||
const HCF_HIGHCONTRASTON = 0x00000001
|
||||
|
||||
// BackdropType defines the type of translucency we wish to use
|
||||
type BackdropType int32
|
||||
|
||||
func dwmSetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
|
||||
ret, _, err := procDwmSetWindowAttribute.Call(
|
||||
uintptr(hwnd),
|
||||
uintptr(dwAttribute),
|
||||
uintptr(pvAttribute),
|
||||
cbAttribute)
|
||||
if ret != 0 {
|
||||
_ = err
|
||||
// println(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func SupportsThemes() bool {
|
||||
// We can't support Windows versions before 17763
|
||||
return IsWindowsVersionAtLeast(10, 0, 17763)
|
||||
}
|
||||
|
||||
func SupportsCustomThemes() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 17763)
|
||||
}
|
||||
|
||||
func SupportsBackdropTypes() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 22621)
|
||||
}
|
||||
|
||||
func SupportsImmersiveDarkMode() bool {
|
||||
return IsWindowsVersionAtLeast(10, 0, 18985)
|
||||
}
|
||||
|
||||
func SetTheme(hwnd HWND, useDarkMode bool) {
|
||||
if SupportsThemes() {
|
||||
attr := DwmwaUseImmersiveDarkModeBefore20h1
|
||||
if SupportsImmersiveDarkMode() {
|
||||
attr = DwmwaUseImmersiveDarkMode
|
||||
}
|
||||
var winDark int32
|
||||
if useDarkMode {
|
||||
winDark = 1
|
||||
}
|
||||
dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
|
||||
}
|
||||
}
|
||||
|
||||
func EnableTranslucency(hwnd HWND, backdrop BackdropType) {
|
||||
if SupportsBackdropTypes() {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaSystemBackdropType, unsafe.Pointer(&backdrop), unsafe.Sizeof(backdrop))
|
||||
} else {
|
||||
println("Warning: Translucency type unavailable on Windows < 22621")
|
||||
}
|
||||
}
|
||||
|
||||
func SetTitleBarColour(hwnd HWND, titleBarColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaCaptionColor, unsafe.Pointer(&titleBarColour), unsafe.Sizeof(titleBarColour))
|
||||
}
|
||||
|
||||
func SetTitleTextColour(hwnd HWND, titleTextColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaTextColor, unsafe.Pointer(&titleTextColour), unsafe.Sizeof(titleTextColour))
|
||||
}
|
||||
|
||||
func SetBorderColour(hwnd HWND, titleBorderColour int32) {
|
||||
dwmSetWindowAttribute(hwnd, DwmwaBorderColor, unsafe.Pointer(&titleBorderColour), unsafe.Sizeof(titleBorderColour))
|
||||
}
|
||||
|
||||
func SetWindowTheme(hwnd HWND, appName string, subIdList string) uintptr {
|
||||
var subID uintptr
|
||||
if subIdList != "" {
|
||||
subID = MustStringToUTF16uintptr(subIdList)
|
||||
}
|
||||
ret, _, _ := procSetWindowTheme.Call(
|
||||
uintptr(hwnd),
|
||||
MustStringToUTF16uintptr(appName),
|
||||
subID,
|
||||
)
|
||||
|
||||
return ret
|
||||
}
|
||||
func IsCurrentlyDarkMode() bool {
|
||||
key, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`, registry.QUERY_VALUE)
|
||||
if err != nil {
|
||||
|
|
@ -17,3 +109,21 @@ func IsCurrentlyDarkMode() bool {
|
|||
}
|
||||
return AppsUseLightTheme == 0
|
||||
}
|
||||
|
||||
type highContrast struct {
|
||||
CbSize uint32
|
||||
DwFlags uint32
|
||||
LpszDefaultScheme *int16
|
||||
}
|
||||
|
||||
func IsCurrentlyHighContrastMode() bool {
|
||||
var result highContrast
|
||||
result.CbSize = uint32(unsafe.Sizeof(result))
|
||||
res, _, err := procSystemParametersInfo.Call(SPI_GETHIGHCONTRAST, uintptr(result.CbSize), uintptr(unsafe.Pointer(&result)), 0)
|
||||
if res == 0 {
|
||||
_ = err
|
||||
return false
|
||||
}
|
||||
r := result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON
|
||||
return r
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue