| 1 | //go:build windows |
| 2 | |
| 3 | package w32 |
| 4 | |
| 5 | import ( |
| 6 | "syscall" |
| 7 | "unicode/utf16" |
| 8 | "unsafe" |
| 9 | |
| 10 | "golang.org/x/sys/windows" |
| 11 | ) |
| 12 | |
| 13 | var ( |
| 14 | ole32 = windows.NewLazySystemDLL("ole32") |
| 15 | Ole32CoInitializeEx = ole32.NewProc("CoInitializeEx") |
| 16 | |
| 17 | kernel32 = windows.NewLazySystemDLL("kernel32") |
| 18 | Kernel32GetCurrentThreadID = kernel32.NewProc("GetCurrentThreadId") |
| 19 | |
| 20 | shlwapi = windows.NewLazySystemDLL("shlwapi") |
| 21 | shlwapiSHCreateMemStream = shlwapi.NewProc("SHCreateMemStream") |
| 22 | |
| 23 | user32 = windows.NewLazySystemDLL("user32") |
| 24 | User32LoadImageW = user32.NewProc("LoadImageW") |
| 25 | User32GetSystemMetrics = user32.NewProc("GetSystemMetrics") |
| 26 | User32RegisterClassExW = user32.NewProc("RegisterClassExW") |
| 27 | User32CreateWindowExW = user32.NewProc("CreateWindowExW") |
| 28 | User32DestroyWindow = user32.NewProc("DestroyWindow") |
| 29 | User32ShowWindow = user32.NewProc("ShowWindow") |
| 30 | User32UpdateWindow = user32.NewProc("UpdateWindow") |
| 31 | User32SetFocus = user32.NewProc("SetFocus") |
| 32 | User32GetMessageW = user32.NewProc("GetMessageW") |
| 33 | User32TranslateMessage = user32.NewProc("TranslateMessage") |
| 34 | User32DispatchMessageW = user32.NewProc("DispatchMessageW") |
| 35 | User32DefWindowProcW = user32.NewProc("DefWindowProcW") |
| 36 | User32GetClientRect = user32.NewProc("GetClientRect") |
| 37 | User32PostQuitMessage = user32.NewProc("PostQuitMessage") |
| 38 | User32SetWindowTextW = user32.NewProc("SetWindowTextW") |
| 39 | User32PostThreadMessageW = user32.NewProc("PostThreadMessageW") |
| 40 | User32GetWindowLongPtrW = user32.NewProc("GetWindowLongPtrW") |
| 41 | User32SetWindowLongPtrW = user32.NewProc("SetWindowLongPtrW") |
| 42 | User32AdjustWindowRect = user32.NewProc("AdjustWindowRect") |
| 43 | User32SetWindowPos = user32.NewProc("SetWindowPos") |
| 44 | ) |
| 45 | |
| 46 | const ( |
| 47 | SystemMetricsCxIcon = 11 |
| 48 | SystemMetricsCyIcon = 12 |
| 49 | ) |
| 50 | |
| 51 | const ( |
| 52 | COINIT_APARTMENTTHREADED = 0x2 |
| 53 | COINIT_MULTITHREADED = 0x0 |
| 54 | COINIT_DISABLE_OLE1DDE = 0x4 |
| 55 | COINIT_SPEED_OVER_MEMORY = 0x8 |
| 56 | ) |
| 57 | |
| 58 | const ( |
| 59 | SWShow = 5 |
| 60 | ) |
| 61 | |
| 62 | const ( |
| 63 | SWPNoZOrder = 0x0004 |
| 64 | SWPNoActivate = 0x0010 |
| 65 | SWPNoMove = 0x0002 |
| 66 | SWPFrameChanged = 0x0020 |
| 67 | ) |
| 68 | |
| 69 | const ( |
| 70 | WMDestroy = 0x0002 |
| 71 | WMMove = 0x0003 |
| 72 | WMSize = 0x0005 |
| 73 | WMClose = 0x0010 |
| 74 | WMQuit = 0x0012 |
| 75 | WMGetMinMaxInfo = 0x0024 |
| 76 | WMNCLButtonDown = 0x00A1 |
| 77 | WMMoving = 0x0216 |
| 78 | WMApp = 0x8000 |
| 79 | ) |
| 80 | |
| 81 | const ( |
| 82 | GWLStyle = -16 |
| 83 | ) |
| 84 | |
| 85 | const ( |
| 86 | WSOverlapped = 0x00000000 |
| 87 | WSMaximizeBox = 0x00020000 |
| 88 | WSThickFrame = 0x00040000 |
| 89 | WSCaption = 0x00C00000 |
| 90 | WSSysMenu = 0x00080000 |
| 91 | WSMinimizeBox = 0x00020000 |
| 92 | WSOverlappedWindow = (WSOverlapped | WSCaption | WSSysMenu | WSThickFrame | WSMinimizeBox | WSMaximizeBox) |
| 93 | ) |
| 94 | |
| 95 | type WndClassExW struct { |
| 96 | CbSize uint32 |
| 97 | Style uint32 |
| 98 | LpfnWndProc uintptr |
| 99 | CnClsExtra int32 |
| 100 | CbWndExtra int32 |
| 101 | HInstance windows.Handle |
| 102 | HIcon windows.Handle |
| 103 | HCursor windows.Handle |
| 104 | HbrBackground windows.Handle |
| 105 | LpszMenuName *uint16 |
| 106 | LpszClassName *uint16 |
| 107 | HIconSm windows.Handle |
| 108 | } |
| 109 | |
| 110 | type Rect struct { |
| 111 | Left int32 |
| 112 | Top int32 |
| 113 | Right int32 |
| 114 | Bottom int32 |
| 115 | } |
| 116 | |
| 117 | type MinMaxInfo struct { |
| 118 | PtReserved Point |
| 119 | PtMaxSize Point |
| 120 | PtMaxPosition Point |
| 121 | PtMinTrackSize Point |
| 122 | PtMaxTrackSize Point |
| 123 | } |
| 124 | |
| 125 | type Point struct { |
| 126 | X, Y int32 |
| 127 | } |
| 128 | |
| 129 | type Msg struct { |
| 130 | Hwnd syscall.Handle |
| 131 | Message uint32 |
| 132 | WParam uintptr |
| 133 | LParam uintptr |
| 134 | Time uint32 |
| 135 | Pt Point |
| 136 | LPrivate uint32 |
| 137 | } |
| 138 | |
| 139 | func Utf16PtrToString(p *uint16) string { |
| 140 | if p == nil { |
| 141 | return "" |
| 142 | } |
| 143 | // Find NUL terminator. |
| 144 | end := unsafe.Pointer(p) |
| 145 | n := 0 |
| 146 | for *(*uint16)(end) != 0 { |
| 147 | end = unsafe.Pointer(uintptr(end) + unsafe.Sizeof(*p)) |
| 148 | n++ |
| 149 | } |
| 150 | s := (*[(1 << 30) - 1]uint16)(unsafe.Pointer(p))[:n:n] |
| 151 | return string(utf16.Decode(s)) |
| 152 | } |
| 153 | |
| 154 | func SHCreateMemStream(data []byte) (uintptr, error) { |
| 155 | ret, _, err := shlwapiSHCreateMemStream.Call( |
| 156 | uintptr(unsafe.Pointer(&data[0])), |
| 157 | uintptr(len(data)), |
| 158 | ) |
| 159 | if ret == 0 { |
| 160 | return 0, err |
| 161 | } |
| 162 | |
| 163 | return ret, nil |
| 164 | } |
| 165 | |
| 166 | const CW_USEDEFAULT = 0x80000000 |
| 167 | |
| 168 | // GetClientRect retrieves the coordinates of a window's client area. The client coordinates specify the upper-left and lower-right corners of the |
| 169 | // client area. Because client coordinates are relative to the upper-left corner of a window's client area, the coordinates of the upper-left |
| 170 | // corner are (0,0). |
| 171 | func GetClientRect(hwnd uintptr) (Rect, error) { |
| 172 | var rect Rect |
| 173 | ret, _, err := User32GetClientRect.Call(hwnd, uintptr(unsafe.Pointer(&rect))) |
| 174 | if ret == 0 { |
| 175 | return Rect{}, err |
| 176 | } |
| 177 | |
| 178 | return rect, nil |
| 179 | } |
| 180 | |
| 181 | // DefWindowProc calls the default window procedure to provide default processing for any window messages that an application does not process. |
| 182 | func DefWindowProc(hwnd, msg, wparam, lparam uintptr) uintptr { |
| 183 | ret, _, _ := User32DefWindowProcW.Call(hwnd, msg, wparam, lparam) |
| 184 | return ret |
| 185 | } |
| 186 | |
| 187 | // DestroyWindow destroys the specified window. The function sends WM_DESTROY and WM_NCDESTROY messages to the window |
| 188 | // to deactivate it and remove the keyboard focus from it. |
| 189 | func DestroyWindow(hwnd uintptr) error { |
| 190 | ret, _, err := User32DestroyWindow.Call(hwnd) |
| 191 | if ret == 0 { |
| 192 | return err |
| 193 | } |
| 194 | return nil |
| 195 | } |
| 196 |