github.com/secoba/wails/v2@v2.6.4/internal/frontend/desktop/windows/win32/window.go (about) 1 //go:build windows 2 3 package win32 4 5 import ( 6 "fmt" 7 "log" 8 "strconv" 9 "syscall" 10 "unsafe" 11 12 "github.com/secoba/wails/v2/internal/frontend/desktop/windows/winc" 13 ) 14 15 const ( 16 WS_MAXIMIZE = 0x01000000 17 WS_MINIMIZE = 0x20000000 18 19 GWL_STYLE = -16 20 21 MONITOR_DEFAULTTOPRIMARY = 0x00000001 22 ) 23 24 const ( 25 SW_HIDE = 0 26 SW_NORMAL = 1 27 SW_SHOWNORMAL = 1 28 SW_SHOWMINIMIZED = 2 29 SW_MAXIMIZE = 3 30 SW_SHOWMAXIMIZED = 3 31 SW_SHOWNOACTIVATE = 4 32 SW_SHOW = 5 33 SW_MINIMIZE = 6 34 SW_SHOWMINNOACTIVE = 7 35 SW_SHOWNA = 8 36 SW_RESTORE = 9 37 SW_SHOWDEFAULT = 10 38 SW_FORCEMINIMIZE = 11 39 ) 40 41 const ( 42 GCLP_HBRBACKGROUND int32 = -10 43 ) 44 45 // Power 46 const ( 47 // WM_POWERBROADCAST - Notifies applications that a power-management event has occurred. 48 WM_POWERBROADCAST = 536 49 50 // PBT_APMPOWERSTATUSCHANGE - Power status has changed. 51 PBT_APMPOWERSTATUSCHANGE = 10 52 53 // PBT_APMRESUMEAUTOMATIC -Operation is resuming automatically from a low-power state. This message is sent every time the system resumes. 54 PBT_APMRESUMEAUTOMATIC = 18 55 56 // PBT_APMRESUMESUSPEND - Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key. 57 PBT_APMRESUMESUSPEND = 7 58 59 // PBT_APMSUSPEND - System is suspending operation. 60 PBT_APMSUSPEND = 4 61 62 // PBT_POWERSETTINGCHANGE - A power setting change event has been received. 63 PBT_POWERSETTINGCHANGE = 32787 64 ) 65 66 // http://msdn.microsoft.com/en-us/library/windows/desktop/bb773244.aspx 67 type MARGINS struct { 68 CxLeftWidth, CxRightWidth, CyTopHeight, CyBottomHeight int32 69 } 70 71 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd162897.aspx 72 type RECT struct { 73 Left, Top, Right, Bottom int32 74 } 75 76 // http://msdn.microsoft.com/en-us/library/windows/desktop/dd145065.aspx 77 type MONITORINFO struct { 78 CbSize uint32 79 RcMonitor RECT 80 RcWork RECT 81 DwFlags uint32 82 } 83 84 func ExtendFrameIntoClientArea(hwnd uintptr, extend bool) { 85 // -1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11) 86 // Also shows the caption buttons if transparent ant translucent but they don't work. 87 // 0: Adds the default frame styling but no aero shadow, does not show the caption buttons. 88 // 1: Adds the default frame styling (aero shadow and e.g. rounded corners on Windows 11) but no caption buttons 89 // are shown if transparent ant translucent. 90 var margins MARGINS 91 if extend { 92 margins = MARGINS{1, 1, 1, 1} // Only extend 1 pixel to have the default frame styling but no caption buttons 93 } 94 if err := dwmExtendFrameIntoClientArea(hwnd, &margins); err != nil { 95 log.Fatal(fmt.Errorf("DwmExtendFrameIntoClientArea failed: %s", err)) 96 } 97 } 98 99 func IsVisible(hwnd uintptr) bool { 100 ret, _, _ := procIsWindowVisible.Call(hwnd) 101 return ret != 0 102 } 103 104 func IsWindowFullScreen(hwnd uintptr) bool { 105 wRect := GetWindowRect(hwnd) 106 m := MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY) 107 var mi MONITORINFO 108 mi.CbSize = uint32(unsafe.Sizeof(mi)) 109 if !GetMonitorInfo(m, &mi) { 110 return false 111 } 112 return wRect.Left == mi.RcMonitor.Left && 113 wRect.Top == mi.RcMonitor.Top && 114 wRect.Right == mi.RcMonitor.Right && 115 wRect.Bottom == mi.RcMonitor.Bottom 116 } 117 118 func IsWindowMaximised(hwnd uintptr) bool { 119 style := uint32(getWindowLong(hwnd, GWL_STYLE)) 120 return style&WS_MAXIMIZE != 0 121 } 122 func IsWindowMinimised(hwnd uintptr) bool { 123 style := uint32(getWindowLong(hwnd, GWL_STYLE)) 124 return style&WS_MINIMIZE != 0 125 } 126 127 func RestoreWindow(hwnd uintptr) { 128 showWindow(hwnd, SW_RESTORE) 129 } 130 131 func ShowWindow(hwnd uintptr) { 132 showWindow(hwnd, SW_SHOW) 133 } 134 135 func ShowWindowMaximised(hwnd uintptr) { 136 showWindow(hwnd, SW_MAXIMIZE) 137 } 138 func ShowWindowMinimised(hwnd uintptr) { 139 showWindow(hwnd, SW_MINIMIZE) 140 } 141 142 func SetBackgroundColour(hwnd uintptr, r, g, b uint8) { 143 col := winc.RGB(r, g, b) 144 hbrush, _, _ := procCreateSolidBrush.Call(uintptr(col)) 145 setClassLongPtr(hwnd, GCLP_HBRBACKGROUND, hbrush) 146 } 147 148 func IsWindowNormal(hwnd uintptr) bool { 149 return !IsWindowMaximised(hwnd) && !IsWindowMinimised(hwnd) && !IsWindowFullScreen(hwnd) 150 } 151 152 func dwmExtendFrameIntoClientArea(hwnd uintptr, margins *MARGINS) error { 153 ret, _, _ := procDwmExtendFrameIntoClientArea.Call( 154 hwnd, 155 uintptr(unsafe.Pointer(margins))) 156 157 if ret != 0 { 158 return syscall.GetLastError() 159 } 160 161 return nil 162 } 163 164 func setClassLongPtr(hwnd uintptr, param int32, val uintptr) bool { 165 proc := procSetClassLongPtr 166 if strconv.IntSize == 32 { 167 /* 168 https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclasslongptrw 169 Note: To write code that is compatible with both 32-bit and 64-bit Windows, use SetClassLongPtr. 170 When compiling for 32-bit Windows, SetClassLongPtr is defined as a call to the SetClassLong function 171 172 => We have to do this dynamically when directly calling the DLL procedures 173 */ 174 proc = procSetClassLong 175 } 176 177 ret, _, _ := proc.Call( 178 hwnd, 179 uintptr(param), 180 val, 181 ) 182 return ret != 0 183 } 184 185 func getWindowLong(hwnd uintptr, index int) int32 { 186 ret, _, _ := procGetWindowLong.Call( 187 hwnd, 188 uintptr(index)) 189 190 return int32(ret) 191 } 192 193 func showWindow(hwnd uintptr, cmdshow int) bool { 194 ret, _, _ := procShowWindow.Call( 195 hwnd, 196 uintptr(cmdshow)) 197 return ret != 0 198 } 199 200 func GetWindowRect(hwnd uintptr) *RECT { 201 var rect RECT 202 procGetWindowRect.Call( 203 hwnd, 204 uintptr(unsafe.Pointer(&rect))) 205 206 return &rect 207 } 208 209 func MonitorFromWindow(hwnd uintptr, dwFlags uint32) HMONITOR { 210 ret, _, _ := procMonitorFromWindow.Call( 211 hwnd, 212 uintptr(dwFlags), 213 ) 214 return HMONITOR(ret) 215 } 216 217 func GetMonitorInfo(hMonitor HMONITOR, lmpi *MONITORINFO) bool { 218 ret, _, _ := procGetMonitorInfo.Call( 219 uintptr(hMonitor), 220 uintptr(unsafe.Pointer(lmpi)), 221 ) 222 return ret != 0 223 }