Menu to follow theme

This commit is contained in:
Lea Anthony 2022-10-08 10:10:39 +11:00
commit c5ad7de9cf
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
3 changed files with 192 additions and 0 deletions

View file

@ -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 {

View file

@ -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 {

View file

@ -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
}