github.com/AlpineAIO/wails/v2@v2.0.0-beta.32.0.20240505041856-1047a8fa5fef/internal/platform/win32/theme.go (about) 1 //go:build windows 2 3 package win32 4 5 import ( 6 "golang.org/x/sys/windows/registry" 7 "unsafe" 8 ) 9 10 type DWMWINDOWATTRIBUTE int32 11 12 const DwmwaUseImmersiveDarkModeBefore20h1 DWMWINDOWATTRIBUTE = 19 13 const DwmwaUseImmersiveDarkMode DWMWINDOWATTRIBUTE = 20 14 const DwmwaBorderColor DWMWINDOWATTRIBUTE = 34 15 const DwmwaCaptionColor DWMWINDOWATTRIBUTE = 35 16 const DwmwaTextColor DWMWINDOWATTRIBUTE = 36 17 const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38 18 19 const SPI_GETHIGHCONTRAST = 0x0042 20 const HCF_HIGHCONTRASTON = 0x00000001 21 const WCA_ACCENT_POLICY WINDOWCOMPOSITIONATTRIB = 19 22 23 type ACCENT_STATE DWORD 24 25 const ( 26 ACCENT_DISABLED ACCENT_STATE = 0 27 ACCENT_ENABLE_GRADIENT ACCENT_STATE = 1 28 ACCENT_ENABLE_TRANSPARENTGRADIENT ACCENT_STATE = 2 29 ACCENT_ENABLE_BLURBEHIND ACCENT_STATE = 3 30 ACCENT_ENABLE_ACRYLICBLURBEHIND ACCENT_STATE = 4 // RS4 1803 31 ACCENT_ENABLE_HOSTBACKDROP ACCENT_STATE = 5 // RS5 1809 32 ACCENT_INVALID_STATE ACCENT_STATE = 6 33 ) 34 35 type ACCENT_POLICY struct { 36 AccentState ACCENT_STATE 37 AccentFlags DWORD 38 GradientColor DWORD 39 AnimationId DWORD 40 } 41 42 type WINDOWCOMPOSITIONATTRIBDATA struct { 43 Attrib WINDOWCOMPOSITIONATTRIB 44 PvData unsafe.Pointer 45 CbData uintptr 46 } 47 48 type WINDOWCOMPOSITIONATTRIB DWORD 49 50 // BackdropType defines the type of translucency we wish to use 51 type BackdropType int32 52 53 const ( 54 BackdropTypeAuto BackdropType = 0 55 BackdropTypeNone BackdropType = 1 56 BackdropTypeMica BackdropType = 2 57 BackdropTypeAcrylic BackdropType = 3 58 BackdropTypeTabbed BackdropType = 4 59 ) 60 61 func dwmSetWindowAttribute(hwnd HWND, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) { 62 ret, _, err := procDwmSetWindowAttribute.Call( 63 uintptr(hwnd), 64 uintptr(dwAttribute), 65 uintptr(pvAttribute), 66 cbAttribute) 67 if ret != 0 { 68 _ = err 69 // println(err.Error()) 70 } 71 } 72 73 func SupportsThemes() bool { 74 // We can't support Windows versions before 17763 75 return IsWindowsVersionAtLeast(10, 0, 17763) 76 } 77 78 func SupportsCustomThemes() bool { 79 return IsWindowsVersionAtLeast(10, 0, 17763) 80 } 81 82 func SupportsBackdropTypes() bool { 83 return IsWindowsVersionAtLeast(10, 0, 22621) 84 } 85 86 func SupportsImmersiveDarkMode() bool { 87 return IsWindowsVersionAtLeast(10, 0, 18985) 88 } 89 90 func SetTheme(hwnd HWND, useDarkMode bool) { 91 if SupportsThemes() { 92 attr := DwmwaUseImmersiveDarkModeBefore20h1 93 if SupportsImmersiveDarkMode() { 94 attr = DwmwaUseImmersiveDarkMode 95 } 96 var winDark int32 97 if useDarkMode { 98 winDark = 1 99 } 100 dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark)) 101 } 102 } 103 104 func EnableBlurBehind(hwnd HWND) { 105 var accent = ACCENT_POLICY{ 106 AccentState: ACCENT_ENABLE_ACRYLICBLURBEHIND, 107 AccentFlags: 0x2, 108 } 109 var data WINDOWCOMPOSITIONATTRIBDATA 110 data.Attrib = WCA_ACCENT_POLICY 111 data.PvData = unsafe.Pointer(&accent) 112 data.CbData = unsafe.Sizeof(accent) 113 114 SetWindowCompositionAttribute(hwnd, &data) 115 } 116 117 func SetWindowCompositionAttribute(hwnd HWND, data *WINDOWCOMPOSITIONATTRIBDATA) bool { 118 if procSetWindowCompositionAttribute != nil { 119 ret, _, _ := procSetWindowCompositionAttribute.Call( 120 uintptr(hwnd), 121 uintptr(unsafe.Pointer(data)), 122 ) 123 return ret != 0 124 } 125 return false 126 } 127 128 func EnableTranslucency(hwnd HWND, backdrop BackdropType) { 129 if SupportsBackdropTypes() { 130 dwmSetWindowAttribute(hwnd, DwmwaSystemBackdropType, unsafe.Pointer(&backdrop), unsafe.Sizeof(backdrop)) 131 } else { 132 println("Warning: Translucency type unavailable on Windows < 22621") 133 } 134 } 135 136 func SetTitleBarColour(hwnd HWND, titleBarColour int32) { 137 dwmSetWindowAttribute(hwnd, DwmwaCaptionColor, unsafe.Pointer(&titleBarColour), unsafe.Sizeof(titleBarColour)) 138 } 139 140 func SetTitleTextColour(hwnd HWND, titleTextColour int32) { 141 dwmSetWindowAttribute(hwnd, DwmwaTextColor, unsafe.Pointer(&titleTextColour), unsafe.Sizeof(titleTextColour)) 142 } 143 144 func SetBorderColour(hwnd HWND, titleBorderColour int32) { 145 dwmSetWindowAttribute(hwnd, DwmwaBorderColor, unsafe.Pointer(&titleBorderColour), unsafe.Sizeof(titleBorderColour)) 146 } 147 148 func SetWindowTheme(hwnd HWND, appName string, subIdList string) uintptr { 149 var subID uintptr 150 if subIdList != "" { 151 subID = MustStringToUTF16uintptr(subIdList) 152 } 153 ret, _, _ := procSetWindowTheme.Call( 154 uintptr(hwnd), 155 MustStringToUTF16uintptr(appName), 156 subID, 157 ) 158 159 return ret 160 } 161 func IsCurrentlyDarkMode() bool { 162 key, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`, registry.QUERY_VALUE) 163 if err != nil { 164 return false 165 } 166 defer key.Close() 167 168 AppsUseLightTheme, _, err := key.GetIntegerValue("AppsUseLightTheme") 169 if err != nil { 170 return false 171 } 172 return AppsUseLightTheme == 0 173 } 174 175 type highContrast struct { 176 CbSize uint32 177 DwFlags uint32 178 LpszDefaultScheme *int16 179 } 180 181 func IsCurrentlyHighContrastMode() bool { 182 var result highContrast 183 result.CbSize = uint32(unsafe.Sizeof(result)) 184 res, _, err := procSystemParametersInfo.Call(SPI_GETHIGHCONTRAST, uintptr(result.CbSize), uintptr(unsafe.Pointer(&result)), 0) 185 if res == 0 { 186 _ = err 187 return false 188 } 189 r := result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON 190 return r 191 }