github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/win32/theme.go (about)

     1  //go:build windows
     2  
     3  package win32
     4  
     5  import (
     6  	"unsafe"
     7  
     8  	"golang.org/x/sys/windows/registry"
     9  )
    10  
    11  type DWMWINDOWATTRIBUTE int32
    12  
    13  const DwmwaUseImmersiveDarkModeBefore20h1 DWMWINDOWATTRIBUTE = 19
    14  const DwmwaUseImmersiveDarkMode DWMWINDOWATTRIBUTE = 20
    15  const DwmwaBorderColor DWMWINDOWATTRIBUTE = 34
    16  const DwmwaCaptionColor DWMWINDOWATTRIBUTE = 35
    17  const DwmwaTextColor DWMWINDOWATTRIBUTE = 36
    18  const DwmwaSystemBackdropType DWMWINDOWATTRIBUTE = 38
    19  
    20  const SPI_GETHIGHCONTRAST = 0x0042
    21  const HCF_HIGHCONTRASTON = 0x00000001
    22  
    23  // BackdropType defines the type of translucency we wish to use
    24  type BackdropType int32
    25  
    26  func dwmSetWindowAttribute(hwnd uintptr, dwAttribute DWMWINDOWATTRIBUTE, pvAttribute unsafe.Pointer, cbAttribute uintptr) {
    27  	ret, _, err := procDwmSetWindowAttribute.Call(
    28  		hwnd,
    29  		uintptr(dwAttribute),
    30  		uintptr(pvAttribute),
    31  		cbAttribute)
    32  	if ret != 0 {
    33  		_ = err
    34  		// println(err.Error())
    35  	}
    36  }
    37  
    38  func SupportsThemes() bool {
    39  	// We can't support Windows versions before 17763
    40  	return IsWindowsVersionAtLeast(10, 0, 17763)
    41  }
    42  
    43  func SupportsCustomThemes() bool {
    44  	return IsWindowsVersionAtLeast(10, 0, 17763)
    45  }
    46  
    47  func SupportsBackdropTypes() bool {
    48  	return IsWindowsVersionAtLeast(10, 0, 22621)
    49  }
    50  
    51  func SupportsImmersiveDarkMode() bool {
    52  	return IsWindowsVersionAtLeast(10, 0, 18985)
    53  }
    54  
    55  func SetTheme(hwnd uintptr, useDarkMode bool) {
    56  	if SupportsThemes() {
    57  		attr := DwmwaUseImmersiveDarkModeBefore20h1
    58  		if SupportsImmersiveDarkMode() {
    59  			attr = DwmwaUseImmersiveDarkMode
    60  		}
    61  		var winDark int32
    62  		if useDarkMode {
    63  			winDark = 1
    64  		}
    65  		dwmSetWindowAttribute(hwnd, attr, unsafe.Pointer(&winDark), unsafe.Sizeof(winDark))
    66  	}
    67  }
    68  
    69  func EnableTranslucency(hwnd uintptr, backdrop BackdropType) {
    70  	if SupportsBackdropTypes() {
    71  		dwmSetWindowAttribute(hwnd, DwmwaSystemBackdropType, unsafe.Pointer(&backdrop), unsafe.Sizeof(backdrop))
    72  	} else {
    73  		println("Warning: Translucency type unavailable on Windows < 22621")
    74  	}
    75  }
    76  
    77  func SetTitleBarColour(hwnd uintptr, titleBarColour int32) {
    78  	dwmSetWindowAttribute(hwnd, DwmwaCaptionColor, unsafe.Pointer(&titleBarColour), unsafe.Sizeof(titleBarColour))
    79  }
    80  
    81  func SetTitleTextColour(hwnd uintptr, titleTextColour int32) {
    82  	dwmSetWindowAttribute(hwnd, DwmwaTextColor, unsafe.Pointer(&titleTextColour), unsafe.Sizeof(titleTextColour))
    83  }
    84  
    85  func SetBorderColour(hwnd uintptr, titleBorderColour int32) {
    86  	dwmSetWindowAttribute(hwnd, DwmwaBorderColor, unsafe.Pointer(&titleBorderColour), unsafe.Sizeof(titleBorderColour))
    87  }
    88  
    89  func IsCurrentlyDarkMode() bool {
    90  	key, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize`, registry.QUERY_VALUE)
    91  	if err != nil {
    92  		return false
    93  	}
    94  	defer key.Close()
    95  
    96  	AppsUseLightTheme, _, err := key.GetIntegerValue("AppsUseLightTheme")
    97  	if err != nil {
    98  		return false
    99  	}
   100  	return AppsUseLightTheme == 0
   101  }
   102  
   103  type highContrast struct {
   104  	CbSize            uint32
   105  	DwFlags           uint32
   106  	LpszDefaultScheme *int16
   107  }
   108  
   109  func IsCurrentlyHighContrastMode() bool {
   110  	var result highContrast
   111  	result.CbSize = uint32(unsafe.Sizeof(result))
   112  	res, _, err := procSystemParametersInfo.Call(SPI_GETHIGHCONTRAST, uintptr(result.CbSize), uintptr(unsafe.Pointer(&result)), 0)
   113  	if res == 0 {
   114  		_ = err
   115  		return false
   116  	}
   117  	r := result.DwFlags&HCF_HIGHCONTRASTON == HCF_HIGHCONTRASTON
   118  	return r
   119  }