mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-07 18:35:34 +00:00
app/internal/windows: split out Windows syscalls from package window
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+116
-551
@@ -4,7 +4,6 @@ package window
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"image"
|
"image"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -14,6 +13,8 @@ import (
|
|||||||
|
|
||||||
syscall "golang.org/x/sys/windows"
|
syscall "golang.org/x/sys/windows"
|
||||||
|
|
||||||
|
"gioui.org/app/internal/windows"
|
||||||
|
|
||||||
"gioui.org/f32"
|
"gioui.org/f32"
|
||||||
"gioui.org/io/key"
|
"gioui.org/io/key"
|
||||||
"gioui.org/io/pointer"
|
"gioui.org/io/pointer"
|
||||||
@@ -22,39 +23,6 @@ import (
|
|||||||
|
|
||||||
var winMap = make(map[syscall.Handle]*window)
|
var winMap = make(map[syscall.Handle]*window)
|
||||||
|
|
||||||
type rect struct {
|
|
||||||
left, top, right, bottom int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type wndClassEx struct {
|
|
||||||
cbSize uint32
|
|
||||||
style uint32
|
|
||||||
lpfnWndProc uintptr
|
|
||||||
cnClsExtra int32
|
|
||||||
cbWndExtra int32
|
|
||||||
hInstance syscall.Handle
|
|
||||||
hIcon syscall.Handle
|
|
||||||
hCursor syscall.Handle
|
|
||||||
hbrBackground syscall.Handle
|
|
||||||
lpszMenuName *uint16
|
|
||||||
lpszClassName *uint16
|
|
||||||
hIconSm syscall.Handle
|
|
||||||
}
|
|
||||||
|
|
||||||
type msg struct {
|
|
||||||
hwnd syscall.Handle
|
|
||||||
message uint32
|
|
||||||
wParam uintptr
|
|
||||||
lParam uintptr
|
|
||||||
time uint32
|
|
||||||
pt point
|
|
||||||
lPrivate uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type point struct {
|
|
||||||
x, y int32
|
|
||||||
}
|
|
||||||
|
|
||||||
type window struct {
|
type window struct {
|
||||||
hwnd syscall.Handle
|
hwnd syscall.Handle
|
||||||
hdc syscall.Handle
|
hdc syscall.Handle
|
||||||
@@ -69,134 +37,7 @@ type window struct {
|
|||||||
animating bool
|
animating bool
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const _WM_REDRAW = windows.WM_USER + 0
|
||||||
_CS_HREDRAW = 0x0002
|
|
||||||
_CS_VREDRAW = 0x0001
|
|
||||||
_CS_OWNDC = 0x0020
|
|
||||||
|
|
||||||
_CW_USEDEFAULT = -2147483648
|
|
||||||
|
|
||||||
_IDC_ARROW = 32512
|
|
||||||
|
|
||||||
_INFINITE = 0xFFFFFFFF
|
|
||||||
|
|
||||||
_LOGPIXELSX = 88
|
|
||||||
|
|
||||||
_MDT_EFFECTIVE_DPI = 0
|
|
||||||
|
|
||||||
_MONITOR_DEFAULTTOPRIMARY = 1
|
|
||||||
|
|
||||||
_SIZE_MAXIMIZED = 2
|
|
||||||
_SIZE_MINIMIZED = 1
|
|
||||||
_SIZE_RESTORED = 0
|
|
||||||
|
|
||||||
_SW_SHOWDEFAULT = 10
|
|
||||||
|
|
||||||
_USER_TIMER_MINIMUM = 0x0000000A
|
|
||||||
|
|
||||||
_VK_CONTROL = 0x11
|
|
||||||
_VK_LWIN = 0x5B
|
|
||||||
_VK_MENU = 0x12
|
|
||||||
_VK_RWIN = 0x5C
|
|
||||||
_VK_SHIFT = 0x10
|
|
||||||
|
|
||||||
_VK_BACK = 0x08
|
|
||||||
_VK_DELETE = 0x2e
|
|
||||||
_VK_DOWN = 0x28
|
|
||||||
_VK_END = 0x23
|
|
||||||
_VK_ESCAPE = 0x1b
|
|
||||||
_VK_HOME = 0x24
|
|
||||||
_VK_LEFT = 0x25
|
|
||||||
_VK_NEXT = 0x22
|
|
||||||
_VK_PRIOR = 0x21
|
|
||||||
_VK_RIGHT = 0x27
|
|
||||||
_VK_RETURN = 0x0d
|
|
||||||
_VK_SPACE = 0x20
|
|
||||||
_VK_TAB = 0x09
|
|
||||||
_VK_UP = 0x26
|
|
||||||
|
|
||||||
_VK_F1 = 0x70
|
|
||||||
_VK_F2 = 0x71
|
|
||||||
_VK_F3 = 0x72
|
|
||||||
_VK_F4 = 0x73
|
|
||||||
_VK_F5 = 0x74
|
|
||||||
_VK_F6 = 0x75
|
|
||||||
_VK_F7 = 0x76
|
|
||||||
_VK_F8 = 0x77
|
|
||||||
_VK_F9 = 0x78
|
|
||||||
_VK_F10 = 0x79
|
|
||||||
_VK_F11 = 0x7A
|
|
||||||
_VK_F12 = 0x7B
|
|
||||||
|
|
||||||
_VK_OEM_1 = 0xba
|
|
||||||
_VK_OEM_PLUS = 0xbb
|
|
||||||
_VK_OEM_COMMA = 0xbc
|
|
||||||
_VK_OEM_MINUS = 0xbd
|
|
||||||
_VK_OEM_PERIOD = 0xbe
|
|
||||||
_VK_OEM_2 = 0xbf
|
|
||||||
_VK_OEM_3 = 0xc0
|
|
||||||
_VK_OEM_4 = 0xdb
|
|
||||||
_VK_OEM_5 = 0xdc
|
|
||||||
_VK_OEM_6 = 0xdd
|
|
||||||
_VK_OEM_7 = 0xde
|
|
||||||
_VK_OEM_102 = 0xe2
|
|
||||||
|
|
||||||
_UNICODE_NOCHAR = 65535
|
|
||||||
|
|
||||||
_WM_CANCELMODE = 0x001F
|
|
||||||
_WM_CHAR = 0x0102
|
|
||||||
_WM_CREATE = 0x0001
|
|
||||||
_WM_DPICHANGED = 0x02E0
|
|
||||||
_WM_DESTROY = 0x0002
|
|
||||||
_WM_ERASEBKGND = 0x0014
|
|
||||||
_WM_KEYDOWN = 0x0100
|
|
||||||
_WM_KEYUP = 0x0101
|
|
||||||
_WM_LBUTTONDOWN = 0x0201
|
|
||||||
_WM_LBUTTONUP = 0x0202
|
|
||||||
_WM_MBUTTONDOWN = 0x0207
|
|
||||||
_WM_MBUTTONUP = 0x0208
|
|
||||||
_WM_MOUSEMOVE = 0x0200
|
|
||||||
_WM_MOUSEWHEEL = 0x020A
|
|
||||||
_WM_PAINT = 0x000F
|
|
||||||
_WM_QUIT = 0x0012
|
|
||||||
_WM_SETFOCUS = 0x0007
|
|
||||||
_WM_KILLFOCUS = 0x0008
|
|
||||||
_WM_SHOWWINDOW = 0x0018
|
|
||||||
_WM_SIZE = 0x0005
|
|
||||||
_WM_SYSKEYDOWN = 0x0104
|
|
||||||
_WM_RBUTTONDOWN = 0x0204
|
|
||||||
_WM_RBUTTONUP = 0x0205
|
|
||||||
_WM_TIMER = 0x0113
|
|
||||||
_WM_UNICHAR = 0x0109
|
|
||||||
_WM_USER = 0x0400
|
|
||||||
|
|
||||||
_WS_CLIPCHILDREN = 0x00010000
|
|
||||||
_WS_CLIPSIBLINGS = 0x04000000
|
|
||||||
_WS_VISIBLE = 0x10000000
|
|
||||||
_WS_OVERLAPPED = 0x00000000
|
|
||||||
_WS_OVERLAPPEDWINDOW = _WS_OVERLAPPED | _WS_CAPTION | _WS_SYSMENU | _WS_THICKFRAME |
|
|
||||||
_WS_MINIMIZEBOX | _WS_MAXIMIZEBOX
|
|
||||||
_WS_CAPTION = 0x00C00000
|
|
||||||
_WS_SYSMENU = 0x00080000
|
|
||||||
_WS_THICKFRAME = 0x00040000
|
|
||||||
_WS_MINIMIZEBOX = 0x00020000
|
|
||||||
_WS_MAXIMIZEBOX = 0x00010000
|
|
||||||
|
|
||||||
_WS_EX_APPWINDOW = 0x00040000
|
|
||||||
_WS_EX_WINDOWEDGE = 0x00000100
|
|
||||||
|
|
||||||
_QS_ALLINPUT = 0x04FF
|
|
||||||
|
|
||||||
_MWMO_WAITALL = 0x0001
|
|
||||||
_MWMO_INPUTAVAILABLE = 0x0004
|
|
||||||
|
|
||||||
_WAIT_OBJECT_0 = 0
|
|
||||||
|
|
||||||
_PM_REMOVE = 0x0001
|
|
||||||
_PM_NOREMOVE = 0x0000
|
|
||||||
)
|
|
||||||
|
|
||||||
const _WM_REDRAW = _WM_USER + 0
|
|
||||||
|
|
||||||
var onceMu sync.Mutex
|
var onceMu sync.Mutex
|
||||||
var mainDone = make(chan struct{})
|
var mainDone = make(chan struct{})
|
||||||
@@ -227,9 +68,9 @@ func NewWindow(window Callbacks, opts *Options) error {
|
|||||||
w.w = window
|
w.w = window
|
||||||
w.w.SetDriver(w)
|
w.w.SetDriver(w)
|
||||||
defer w.w.Event(system.DestroyEvent{})
|
defer w.w.Event(system.DestroyEvent{})
|
||||||
showWindow(w.hwnd, _SW_SHOWDEFAULT)
|
windows.ShowWindow(w.hwnd, windows.SW_SHOWDEFAULT)
|
||||||
setForegroundWindow(w.hwnd)
|
windows.SetForegroundWindow(w.hwnd)
|
||||||
setFocus(w.hwnd)
|
windows.SetFocus(w.hwnd)
|
||||||
if err := w.loop(); err != nil {
|
if err := w.loop(); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@@ -239,42 +80,42 @@ func NewWindow(window Callbacks, opts *Options) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createNativeWindow(opts *Options) (*window, error) {
|
func createNativeWindow(opts *Options) (*window, error) {
|
||||||
setProcessDPIAware()
|
windows.SetProcessDPIAware()
|
||||||
cfg := configForDC()
|
cfg := configForDC()
|
||||||
hInst, err := getModuleHandle()
|
hInst, err := windows.GetModuleHandle()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
curs, err := loadCursor(_IDC_ARROW)
|
curs, err := windows.LoadCursor(windows.IDC_ARROW)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
wcls := wndClassEx{
|
wcls := windows.WndClassEx{
|
||||||
cbSize: uint32(unsafe.Sizeof(wndClassEx{})),
|
CbSize: uint32(unsafe.Sizeof(windows.WndClassEx{})),
|
||||||
style: _CS_HREDRAW | _CS_VREDRAW | _CS_OWNDC,
|
Style: windows.CS_HREDRAW | windows.CS_VREDRAW | windows.CS_OWNDC,
|
||||||
lpfnWndProc: syscall.NewCallback(windowProc),
|
LpfnWndProc: syscall.NewCallback(windowProc),
|
||||||
hInstance: hInst,
|
HInstance: hInst,
|
||||||
hCursor: curs,
|
HCursor: curs,
|
||||||
lpszClassName: syscall.StringToUTF16Ptr("GioWindow"),
|
LpszClassName: syscall.StringToUTF16Ptr("GioWindow"),
|
||||||
}
|
}
|
||||||
cls, err := registerClassEx(&wcls)
|
cls, err := windows.RegisterClassEx(&wcls)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
wr := rect{
|
wr := windows.Rect{
|
||||||
right: int32(cfg.Px(opts.Width)),
|
Right: int32(cfg.Px(opts.Width)),
|
||||||
bottom: int32(cfg.Px(opts.Height)),
|
Bottom: int32(cfg.Px(opts.Height)),
|
||||||
}
|
}
|
||||||
dwStyle := uint32(_WS_OVERLAPPEDWINDOW)
|
dwStyle := uint32(windows.WS_OVERLAPPEDWINDOW)
|
||||||
dwExStyle := uint32(_WS_EX_APPWINDOW | _WS_EX_WINDOWEDGE)
|
dwExStyle := uint32(windows.WS_EX_APPWINDOW | windows.WS_EX_WINDOWEDGE)
|
||||||
adjustWindowRectEx(&wr, dwStyle, 0, dwExStyle)
|
windows.AdjustWindowRectEx(&wr, dwStyle, 0, dwExStyle)
|
||||||
hwnd, err := createWindowEx(dwExStyle,
|
hwnd, err := windows.CreateWindowEx(dwExStyle,
|
||||||
cls,
|
cls,
|
||||||
opts.Title,
|
opts.Title,
|
||||||
dwStyle|_WS_CLIPSIBLINGS|_WS_CLIPCHILDREN,
|
dwStyle|windows.WS_CLIPSIBLINGS|windows.WS_CLIPCHILDREN,
|
||||||
_CW_USEDEFAULT, _CW_USEDEFAULT,
|
windows.CW_USEDEFAULT, windows.CW_USEDEFAULT,
|
||||||
wr.right-wr.left,
|
wr.Right-wr.Left,
|
||||||
wr.bottom-wr.top,
|
wr.Bottom-wr.Top,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
hInst,
|
hInst,
|
||||||
@@ -285,7 +126,7 @@ func createNativeWindow(opts *Options) (*window, error) {
|
|||||||
w := &window{
|
w := &window{
|
||||||
hwnd: hwnd,
|
hwnd: hwnd,
|
||||||
}
|
}
|
||||||
w.hdc, err = getDC(hwnd)
|
w.hdc, err = windows.GetDC(hwnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -295,86 +136,86 @@ func createNativeWindow(opts *Options) (*window, error) {
|
|||||||
func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr {
|
func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr {
|
||||||
w := winMap[hwnd]
|
w := winMap[hwnd]
|
||||||
switch msg {
|
switch msg {
|
||||||
case _WM_UNICHAR:
|
case windows.WM_UNICHAR:
|
||||||
if wParam == _UNICODE_NOCHAR {
|
if wParam == windows.UNICODE_NOCHAR {
|
||||||
// Tell the system that we accept WM_UNICHAR messages.
|
// Tell the system that we accept WM_UNICHAR messages.
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
fallthrough
|
fallthrough
|
||||||
case _WM_CHAR:
|
case windows.WM_CHAR:
|
||||||
if r := rune(wParam); unicode.IsPrint(r) {
|
if r := rune(wParam); unicode.IsPrint(r) {
|
||||||
w.w.Event(key.EditEvent{Text: string(r)})
|
w.w.Event(key.EditEvent{Text: string(r)})
|
||||||
}
|
}
|
||||||
// The message is processed.
|
// The message is processed.
|
||||||
return 1
|
return 1
|
||||||
case _WM_DPICHANGED:
|
case windows.WM_DPICHANGED:
|
||||||
// Let Windows know we're prepared for runtime DPI changes.
|
// Let Windows know we're prepared for runtime DPI changes.
|
||||||
return 1
|
return 1
|
||||||
case _WM_ERASEBKGND:
|
case windows.WM_ERASEBKGND:
|
||||||
// Avoid flickering between GPU content and background color.
|
// Avoid flickering between GPU content and background color.
|
||||||
return 1
|
return 1
|
||||||
case _WM_KEYDOWN, _WM_SYSKEYDOWN:
|
case windows.WM_KEYDOWN, windows.WM_SYSKEYDOWN:
|
||||||
if n, ok := convertKeyCode(wParam); ok {
|
if n, ok := convertKeyCode(wParam); ok {
|
||||||
w.w.Event(key.Event{Name: n, Modifiers: getModifiers()})
|
w.w.Event(key.Event{Name: n, Modifiers: getModifiers()})
|
||||||
}
|
}
|
||||||
case _WM_LBUTTONDOWN:
|
case windows.WM_LBUTTONDOWN:
|
||||||
w.pointerButton(pointer.ButtonLeft, true, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonLeft, true, lParam, getModifiers())
|
||||||
case _WM_LBUTTONUP:
|
case windows.WM_LBUTTONUP:
|
||||||
w.pointerButton(pointer.ButtonLeft, false, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonLeft, false, lParam, getModifiers())
|
||||||
case _WM_RBUTTONDOWN:
|
case windows.WM_RBUTTONDOWN:
|
||||||
w.pointerButton(pointer.ButtonRight, true, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonRight, true, lParam, getModifiers())
|
||||||
case _WM_RBUTTONUP:
|
case windows.WM_RBUTTONUP:
|
||||||
w.pointerButton(pointer.ButtonRight, false, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonRight, false, lParam, getModifiers())
|
||||||
case _WM_MBUTTONDOWN:
|
case windows.WM_MBUTTONDOWN:
|
||||||
w.pointerButton(pointer.ButtonMiddle, true, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonMiddle, true, lParam, getModifiers())
|
||||||
case _WM_MBUTTONUP:
|
case windows.WM_MBUTTONUP:
|
||||||
w.pointerButton(pointer.ButtonMiddle, false, lParam, getModifiers())
|
w.pointerButton(pointer.ButtonMiddle, false, lParam, getModifiers())
|
||||||
case _WM_CANCELMODE:
|
case windows.WM_CANCELMODE:
|
||||||
w.w.Event(pointer.Event{
|
w.w.Event(pointer.Event{
|
||||||
Type: pointer.Cancel,
|
Type: pointer.Cancel,
|
||||||
})
|
})
|
||||||
case _WM_SETFOCUS:
|
case windows.WM_SETFOCUS:
|
||||||
w.w.Event(key.FocusEvent{Focus: true})
|
w.w.Event(key.FocusEvent{Focus: true})
|
||||||
case _WM_KILLFOCUS:
|
case windows.WM_KILLFOCUS:
|
||||||
w.w.Event(key.FocusEvent{Focus: false})
|
w.w.Event(key.FocusEvent{Focus: false})
|
||||||
case _WM_MOUSEMOVE:
|
case windows.WM_MOUSEMOVE:
|
||||||
x, y := coordsFromlParam(lParam)
|
x, y := coordsFromlParam(lParam)
|
||||||
p := f32.Point{X: float32(x), Y: float32(y)}
|
p := f32.Point{X: float32(x), Y: float32(y)}
|
||||||
w.w.Event(pointer.Event{
|
w.w.Event(pointer.Event{
|
||||||
Type: pointer.Move,
|
Type: pointer.Move,
|
||||||
Source: pointer.Mouse,
|
Source: pointer.Mouse,
|
||||||
Position: p,
|
Position: p,
|
||||||
Time: getMessageTime(),
|
Time: windows.GetMessageTime(),
|
||||||
})
|
})
|
||||||
case _WM_MOUSEWHEEL:
|
case windows.WM_MOUSEWHEEL:
|
||||||
w.scrollEvent(wParam, lParam)
|
w.scrollEvent(wParam, lParam)
|
||||||
case _WM_DESTROY:
|
case windows.WM_DESTROY:
|
||||||
w.dead = true
|
w.dead = true
|
||||||
case _WM_PAINT:
|
case windows.WM_PAINT:
|
||||||
w.draw(true)
|
w.draw(true)
|
||||||
case _WM_SIZE:
|
case windows.WM_SIZE:
|
||||||
switch wParam {
|
switch wParam {
|
||||||
case _SIZE_MINIMIZED:
|
case windows.SIZE_MINIMIZED:
|
||||||
w.setStage(system.StagePaused)
|
w.setStage(system.StagePaused)
|
||||||
case _SIZE_MAXIMIZED, _SIZE_RESTORED:
|
case windows.SIZE_MAXIMIZED, windows.SIZE_RESTORED:
|
||||||
w.setStage(system.StageRunning)
|
w.setStage(system.StageRunning)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return defWindowProc(hwnd, msg, wParam, lParam)
|
return windows.DefWindowProc(hwnd, msg, wParam, lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getModifiers() key.Modifiers {
|
func getModifiers() key.Modifiers {
|
||||||
var kmods key.Modifiers
|
var kmods key.Modifiers
|
||||||
if getKeyState(_VK_LWIN)&0x1000 != 0 || getKeyState(_VK_RWIN)&0x1000 != 0 {
|
if windows.GetKeyState(windows.VK_LWIN)&0x1000 != 0 || windows.GetKeyState(windows.VK_RWIN)&0x1000 != 0 {
|
||||||
kmods |= key.ModSuper
|
kmods |= key.ModSuper
|
||||||
}
|
}
|
||||||
if getKeyState(_VK_MENU)&0x1000 != 0 {
|
if windows.GetKeyState(windows.VK_MENU)&0x1000 != 0 {
|
||||||
kmods |= key.ModAlt
|
kmods |= key.ModAlt
|
||||||
}
|
}
|
||||||
if getKeyState(_VK_CONTROL)&0x1000 != 0 {
|
if windows.GetKeyState(windows.VK_CONTROL)&0x1000 != 0 {
|
||||||
kmods |= key.ModCtrl
|
kmods |= key.ModCtrl
|
||||||
}
|
}
|
||||||
if getKeyState(_VK_SHIFT)&0x1000 != 0 {
|
if windows.GetKeyState(windows.VK_SHIFT)&0x1000 != 0 {
|
||||||
kmods |= key.ModShift
|
kmods |= key.ModShift
|
||||||
}
|
}
|
||||||
return kmods
|
return kmods
|
||||||
@@ -385,14 +226,14 @@ func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr,
|
|||||||
if press {
|
if press {
|
||||||
typ = pointer.Press
|
typ = pointer.Press
|
||||||
if w.pointerBtns == 0 {
|
if w.pointerBtns == 0 {
|
||||||
setCapture(w.hwnd)
|
windows.SetCapture(w.hwnd)
|
||||||
}
|
}
|
||||||
w.pointerBtns |= btn
|
w.pointerBtns |= btn
|
||||||
} else {
|
} else {
|
||||||
typ = pointer.Release
|
typ = pointer.Release
|
||||||
w.pointerBtns &^= btn
|
w.pointerBtns &^= btn
|
||||||
if w.pointerBtns == 0 {
|
if w.pointerBtns == 0 {
|
||||||
releaseCapture()
|
windows.ReleaseCapture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
x, y := coordsFromlParam(lParam)
|
x, y := coordsFromlParam(lParam)
|
||||||
@@ -402,7 +243,7 @@ func (w *window) pointerButton(btn pointer.Buttons, press bool, lParam uintptr,
|
|||||||
Source: pointer.Mouse,
|
Source: pointer.Mouse,
|
||||||
Position: p,
|
Position: p,
|
||||||
Buttons: w.pointerBtns,
|
Buttons: w.pointerBtns,
|
||||||
Time: getMessageTime(),
|
Time: windows.GetMessageTime(),
|
||||||
Modifiers: kmods,
|
Modifiers: kmods,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -417,37 +258,37 @@ func (w *window) scrollEvent(wParam, lParam uintptr) {
|
|||||||
x, y := coordsFromlParam(lParam)
|
x, y := coordsFromlParam(lParam)
|
||||||
// The WM_MOUSEWHEEL coordinates are in screen coordinates, in contrast
|
// The WM_MOUSEWHEEL coordinates are in screen coordinates, in contrast
|
||||||
// to other mouse events.
|
// to other mouse events.
|
||||||
np := point{x: int32(x), y: int32(y)}
|
np := windows.Point{X: int32(x), Y: int32(y)}
|
||||||
screenToClient(w.hwnd, &np)
|
windows.ScreenToClient(w.hwnd, &np)
|
||||||
p := f32.Point{X: float32(np.x), Y: float32(np.y)}
|
p := f32.Point{X: float32(np.X), Y: float32(np.Y)}
|
||||||
dist := float32(int16(wParam >> 16))
|
dist := float32(int16(wParam >> 16))
|
||||||
w.w.Event(pointer.Event{
|
w.w.Event(pointer.Event{
|
||||||
Type: pointer.Move,
|
Type: pointer.Move,
|
||||||
Source: pointer.Mouse,
|
Source: pointer.Mouse,
|
||||||
Position: p,
|
Position: p,
|
||||||
Scroll: f32.Point{Y: -dist},
|
Scroll: f32.Point{Y: -dist},
|
||||||
Time: getMessageTime(),
|
Time: windows.GetMessageTime(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20060126-00/?p=32513/
|
// Adapted from https://blogs.msdn.microsoft.com/oldnewthing/20060126-00/?p=32513/
|
||||||
func (w *window) loop() error {
|
func (w *window) loop() error {
|
||||||
msg := new(msg)
|
msg := new(windows.Msg)
|
||||||
for !w.dead {
|
for !w.dead {
|
||||||
w.mu.Lock()
|
w.mu.Lock()
|
||||||
anim := w.animating
|
anim := w.animating
|
||||||
w.mu.Unlock()
|
w.mu.Unlock()
|
||||||
if anim && !peekMessage(msg, w.hwnd, 0, 0, _PM_NOREMOVE) {
|
if anim && !windows.PeekMessage(msg, w.hwnd, 0, 0, windows.PM_NOREMOVE) {
|
||||||
w.draw(false)
|
w.draw(false)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
getMessage(msg, w.hwnd, 0, 0)
|
windows.GetMessage(msg, w.hwnd, 0, 0)
|
||||||
if msg.message == _WM_QUIT {
|
if msg.Message == windows.WM_QUIT {
|
||||||
postQuitMessage(msg.wParam)
|
windows.PostQuitMessage(msg.WParam)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
translateMessage(msg)
|
windows.TranslateMessage(msg)
|
||||||
dispatchMessage(msg)
|
windows.DispatchMessage(msg)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -462,7 +303,7 @@ func (w *window) SetAnimating(anim bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) postRedraw() {
|
func (w *window) postRedraw() {
|
||||||
if err := postMessage(w.hwnd, _WM_REDRAW, 0, 0); err != nil {
|
if err := windows.PostMessage(w.hwnd, _WM_REDRAW, 0, 0); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -473,10 +314,10 @@ func (w *window) setStage(s system.Stage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *window) draw(sync bool) {
|
func (w *window) draw(sync bool) {
|
||||||
var r rect
|
var r windows.Rect
|
||||||
getClientRect(w.hwnd, &r)
|
windows.GetClientRect(w.hwnd, &r)
|
||||||
w.width = int(r.right - r.left)
|
w.width = int(r.Right - r.Left)
|
||||||
w.height = int(r.bottom - r.top)
|
w.height = int(r.Bottom - r.Top)
|
||||||
cfg := configForDC()
|
cfg := configForDC()
|
||||||
cfg.now = time.Now()
|
cfg.now = time.Now()
|
||||||
w.w.Event(FrameEvent{
|
w.w.Event(FrameEvent{
|
||||||
@@ -493,11 +334,11 @@ func (w *window) draw(sync bool) {
|
|||||||
|
|
||||||
func (w *window) destroy() {
|
func (w *window) destroy() {
|
||||||
if w.hdc != 0 {
|
if w.hdc != 0 {
|
||||||
releaseDC(w.hdc)
|
windows.ReleaseDC(w.hdc)
|
||||||
w.hdc = 0
|
w.hdc = 0
|
||||||
}
|
}
|
||||||
if w.hwnd != 0 {
|
if w.hwnd != 0 {
|
||||||
destroyWindow(w.hwnd)
|
windows.DestroyWindow(w.hwnd)
|
||||||
w.hwnd = 0
|
w.hwnd = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -518,79 +359,79 @@ func convertKeyCode(code uintptr) (string, bool) {
|
|||||||
}
|
}
|
||||||
var r string
|
var r string
|
||||||
switch code {
|
switch code {
|
||||||
case _VK_ESCAPE:
|
case windows.VK_ESCAPE:
|
||||||
r = key.NameEscape
|
r = key.NameEscape
|
||||||
case _VK_LEFT:
|
case windows.VK_LEFT:
|
||||||
r = key.NameLeftArrow
|
r = key.NameLeftArrow
|
||||||
case _VK_RIGHT:
|
case windows.VK_RIGHT:
|
||||||
r = key.NameRightArrow
|
r = key.NameRightArrow
|
||||||
case _VK_RETURN:
|
case windows.VK_RETURN:
|
||||||
r = key.NameReturn
|
r = key.NameReturn
|
||||||
case _VK_UP:
|
case windows.VK_UP:
|
||||||
r = key.NameUpArrow
|
r = key.NameUpArrow
|
||||||
case _VK_DOWN:
|
case windows.VK_DOWN:
|
||||||
r = key.NameDownArrow
|
r = key.NameDownArrow
|
||||||
case _VK_HOME:
|
case windows.VK_HOME:
|
||||||
r = key.NameHome
|
r = key.NameHome
|
||||||
case _VK_END:
|
case windows.VK_END:
|
||||||
r = key.NameEnd
|
r = key.NameEnd
|
||||||
case _VK_BACK:
|
case windows.VK_BACK:
|
||||||
r = key.NameDeleteBackward
|
r = key.NameDeleteBackward
|
||||||
case _VK_DELETE:
|
case windows.VK_DELETE:
|
||||||
r = key.NameDeleteForward
|
r = key.NameDeleteForward
|
||||||
case _VK_PRIOR:
|
case windows.VK_PRIOR:
|
||||||
r = key.NamePageUp
|
r = key.NamePageUp
|
||||||
case _VK_NEXT:
|
case windows.VK_NEXT:
|
||||||
r = key.NamePageDown
|
r = key.NamePageDown
|
||||||
case _VK_F1:
|
case windows.VK_F1:
|
||||||
r = "F1"
|
r = "F1"
|
||||||
case _VK_F2:
|
case windows.VK_F2:
|
||||||
r = "F2"
|
r = "F2"
|
||||||
case _VK_F3:
|
case windows.VK_F3:
|
||||||
r = "F3"
|
r = "F3"
|
||||||
case _VK_F4:
|
case windows.VK_F4:
|
||||||
r = "F4"
|
r = "F4"
|
||||||
case _VK_F5:
|
case windows.VK_F5:
|
||||||
r = "F5"
|
r = "F5"
|
||||||
case _VK_F6:
|
case windows.VK_F6:
|
||||||
r = "F6"
|
r = "F6"
|
||||||
case _VK_F7:
|
case windows.VK_F7:
|
||||||
r = "F7"
|
r = "F7"
|
||||||
case _VK_F8:
|
case windows.VK_F8:
|
||||||
r = "F8"
|
r = "F8"
|
||||||
case _VK_F9:
|
case windows.VK_F9:
|
||||||
r = "F9"
|
r = "F9"
|
||||||
case _VK_F10:
|
case windows.VK_F10:
|
||||||
r = "F10"
|
r = "F10"
|
||||||
case _VK_F11:
|
case windows.VK_F11:
|
||||||
r = "F11"
|
r = "F11"
|
||||||
case _VK_F12:
|
case windows.VK_F12:
|
||||||
r = "F12"
|
r = "F12"
|
||||||
case _VK_TAB:
|
case windows.VK_TAB:
|
||||||
r = key.NameTab
|
r = key.NameTab
|
||||||
case _VK_SPACE:
|
case windows.VK_SPACE:
|
||||||
r = "Space"
|
r = "Space"
|
||||||
case _VK_OEM_1:
|
case windows.VK_OEM_1:
|
||||||
r = ";"
|
r = ";"
|
||||||
case _VK_OEM_PLUS:
|
case windows.VK_OEM_PLUS:
|
||||||
r = "+"
|
r = "+"
|
||||||
case _VK_OEM_COMMA:
|
case windows.VK_OEM_COMMA:
|
||||||
r = ","
|
r = ","
|
||||||
case _VK_OEM_MINUS:
|
case windows.VK_OEM_MINUS:
|
||||||
r = "-"
|
r = "-"
|
||||||
case _VK_OEM_PERIOD:
|
case windows.VK_OEM_PERIOD:
|
||||||
r = "."
|
r = "."
|
||||||
case _VK_OEM_2:
|
case windows.VK_OEM_2:
|
||||||
r = "/"
|
r = "/"
|
||||||
case _VK_OEM_3:
|
case windows.VK_OEM_3:
|
||||||
r = "`"
|
r = "`"
|
||||||
case _VK_OEM_4:
|
case windows.VK_OEM_4:
|
||||||
r = "["
|
r = "["
|
||||||
case _VK_OEM_5, _VK_OEM_102:
|
case windows.VK_OEM_5, windows.VK_OEM_102:
|
||||||
r = "\\"
|
r = "\\"
|
||||||
case _VK_OEM_6:
|
case windows.VK_OEM_6:
|
||||||
r = "]"
|
r = "]"
|
||||||
case _VK_OEM_7:
|
case windows.VK_OEM_7:
|
||||||
r = "'"
|
r = "'"
|
||||||
default:
|
default:
|
||||||
return "", false
|
return "", false
|
||||||
@@ -599,7 +440,7 @@ func convertKeyCode(code uintptr) (string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func configForDC() config {
|
func configForDC() config {
|
||||||
dpi := getSystemDPI()
|
dpi := windows.GetSystemDPI()
|
||||||
const inchPrDp = 1.0 / 96.0
|
const inchPrDp = 1.0 / 96.0
|
||||||
ppdp := float32(dpi) * inchPrDp
|
ppdp := float32(dpi) * inchPrDp
|
||||||
return config{
|
return config{
|
||||||
@@ -607,279 +448,3 @@ func configForDC() config {
|
|||||||
pxPerSp: ppdp,
|
pxPerSp: ppdp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
kernel32 = syscall.NewLazySystemDLL("kernel32.dll")
|
|
||||||
_GetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
|
|
||||||
|
|
||||||
user32 = syscall.NewLazySystemDLL("user32.dll")
|
|
||||||
_AdjustWindowRectEx = user32.NewProc("AdjustWindowRectEx")
|
|
||||||
_CallMsgFilter = user32.NewProc("CallMsgFilterW")
|
|
||||||
_CreateWindowEx = user32.NewProc("CreateWindowExW")
|
|
||||||
_DefWindowProc = user32.NewProc("DefWindowProcW")
|
|
||||||
_DestroyWindow = user32.NewProc("DestroyWindow")
|
|
||||||
_DispatchMessage = user32.NewProc("DispatchMessageW")
|
|
||||||
_GetClientRect = user32.NewProc("GetClientRect")
|
|
||||||
_GetDC = user32.NewProc("GetDC")
|
|
||||||
_GetKeyState = user32.NewProc("GetKeyState")
|
|
||||||
_GetMessage = user32.NewProc("GetMessageW")
|
|
||||||
_GetMessageTime = user32.NewProc("GetMessageTime")
|
|
||||||
_KillTimer = user32.NewProc("KillTimer")
|
|
||||||
_LoadCursor = user32.NewProc("LoadCursorW")
|
|
||||||
_MonitorFromPoint = user32.NewProc("MonitorFromPoint")
|
|
||||||
_MsgWaitForMultipleObjectsEx = user32.NewProc("MsgWaitForMultipleObjectsEx")
|
|
||||||
_PeekMessage = user32.NewProc("PeekMessageW")
|
|
||||||
_PostMessage = user32.NewProc("PostMessageW")
|
|
||||||
_PostQuitMessage = user32.NewProc("PostQuitMessage")
|
|
||||||
_ReleaseCapture = user32.NewProc("ReleaseCapture")
|
|
||||||
_RegisterClassExW = user32.NewProc("RegisterClassExW")
|
|
||||||
_ReleaseDC = user32.NewProc("ReleaseDC")
|
|
||||||
_ScreenToClient = user32.NewProc("ScreenToClient")
|
|
||||||
_ShowWindow = user32.NewProc("ShowWindow")
|
|
||||||
_SetCapture = user32.NewProc("SetCapture")
|
|
||||||
_SetForegroundWindow = user32.NewProc("SetForegroundWindow")
|
|
||||||
_SetFocus = user32.NewProc("SetFocus")
|
|
||||||
_SetProcessDPIAware = user32.NewProc("SetProcessDPIAware")
|
|
||||||
_SetTimer = user32.NewProc("SetTimer")
|
|
||||||
_TranslateMessage = user32.NewProc("TranslateMessage")
|
|
||||||
_UnregisterClass = user32.NewProc("UnregisterClassW")
|
|
||||||
_UpdateWindow = user32.NewProc("UpdateWindow")
|
|
||||||
|
|
||||||
shcore = syscall.NewLazySystemDLL("shcore")
|
|
||||||
_GetDpiForMonitor = shcore.NewProc("GetDpiForMonitor")
|
|
||||||
|
|
||||||
gdi32 = syscall.NewLazySystemDLL("gdi32")
|
|
||||||
_GetDeviceCaps = gdi32.NewProc("GetDeviceCaps")
|
|
||||||
)
|
|
||||||
|
|
||||||
func getModuleHandle() (syscall.Handle, error) {
|
|
||||||
h, _, err := _GetModuleHandleW.Call(uintptr(0))
|
|
||||||
if h == 0 {
|
|
||||||
return 0, fmt.Errorf("GetModuleHandleW failed: %v", err)
|
|
||||||
}
|
|
||||||
return syscall.Handle(h), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func adjustWindowRectEx(r *rect, dwStyle uint32, bMenu int, dwExStyle uint32) {
|
|
||||||
_AdjustWindowRectEx.Call(uintptr(unsafe.Pointer(r)), uintptr(dwStyle), uintptr(bMenu), uintptr(dwExStyle))
|
|
||||||
issue34474KeepAlive(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func callMsgFilter(m *msg, nCode uintptr) bool {
|
|
||||||
r, _, _ := _CallMsgFilter.Call(uintptr(unsafe.Pointer(m)), nCode)
|
|
||||||
issue34474KeepAlive(m)
|
|
||||||
return r != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func createWindowEx(dwExStyle uint32, lpClassName uint16, lpWindowName string, dwStyle uint32, x, y, w, h int32, hWndParent, hMenu, hInstance syscall.Handle, lpParam uintptr) (syscall.Handle, error) {
|
|
||||||
wname := syscall.StringToUTF16Ptr(lpWindowName)
|
|
||||||
hwnd, _, err := _CreateWindowEx.Call(
|
|
||||||
uintptr(dwExStyle),
|
|
||||||
uintptr(lpClassName),
|
|
||||||
uintptr(unsafe.Pointer(wname)),
|
|
||||||
uintptr(dwStyle),
|
|
||||||
uintptr(x), uintptr(y),
|
|
||||||
uintptr(w), uintptr(h),
|
|
||||||
uintptr(hWndParent),
|
|
||||||
uintptr(hMenu),
|
|
||||||
uintptr(hInstance),
|
|
||||||
uintptr(lpParam))
|
|
||||||
issue34474KeepAlive(wname)
|
|
||||||
if hwnd == 0 {
|
|
||||||
return 0, fmt.Errorf("CreateWindowEx failed: %v", err)
|
|
||||||
}
|
|
||||||
return syscall.Handle(hwnd), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func defWindowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
|
|
||||||
r, _, _ := _DefWindowProc.Call(uintptr(hwnd), uintptr(msg), wparam, lparam)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
func destroyWindow(hwnd syscall.Handle) {
|
|
||||||
_DestroyWindow.Call(uintptr(hwnd))
|
|
||||||
}
|
|
||||||
|
|
||||||
func dispatchMessage(m *msg) {
|
|
||||||
_DispatchMessage.Call(uintptr(unsafe.Pointer(m)))
|
|
||||||
issue34474KeepAlive(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getClientRect(hwnd syscall.Handle, r *rect) {
|
|
||||||
_GetClientRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(r)))
|
|
||||||
issue34474KeepAlive(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDC(hwnd syscall.Handle) (syscall.Handle, error) {
|
|
||||||
hdc, _, err := _GetDC.Call(uintptr(hwnd))
|
|
||||||
if hdc == 0 {
|
|
||||||
return 0, fmt.Errorf("GetDC failed: %v", err)
|
|
||||||
}
|
|
||||||
return syscall.Handle(hdc), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDeviceCaps(hdc syscall.Handle, index int32) int {
|
|
||||||
c, _, _ := _GetDeviceCaps.Call(uintptr(hdc), uintptr(index))
|
|
||||||
return int(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getDpiForMonitor(hmonitor syscall.Handle, dpiType uint32) int {
|
|
||||||
var dpiX, dpiY uintptr
|
|
||||||
_GetDpiForMonitor.Call(uintptr(hmonitor), uintptr(dpiType), uintptr(unsafe.Pointer(&dpiX)), uintptr(unsafe.Pointer(&dpiY)))
|
|
||||||
return int(dpiX)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getSystemDPI returns the effective DPI of the system.
|
|
||||||
func getSystemDPI() int {
|
|
||||||
// Check for GetDpiForMonitor, introduced in Windows 8.1.
|
|
||||||
if _GetDpiForMonitor.Find() == nil {
|
|
||||||
hmon := monitorFromPoint(point{}, _MONITOR_DEFAULTTOPRIMARY)
|
|
||||||
return getDpiForMonitor(hmon, _MDT_EFFECTIVE_DPI)
|
|
||||||
} else {
|
|
||||||
// Fall back to the physical device DPI.
|
|
||||||
screenDC, err := getDC(0)
|
|
||||||
if err != nil {
|
|
||||||
return 96
|
|
||||||
}
|
|
||||||
defer releaseDC(screenDC)
|
|
||||||
return getDeviceCaps(screenDC, _LOGPIXELSX)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getKeyState(nVirtKey int32) int16 {
|
|
||||||
c, _, _ := _GetKeyState.Call(uintptr(nVirtKey))
|
|
||||||
return int16(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMessage(m *msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax uint32) int32 {
|
|
||||||
r, _, _ := _GetMessage.Call(uintptr(unsafe.Pointer(m)),
|
|
||||||
uintptr(hwnd),
|
|
||||||
uintptr(wMsgFilterMin),
|
|
||||||
uintptr(wMsgFilterMax))
|
|
||||||
issue34474KeepAlive(m)
|
|
||||||
return int32(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMessageTime() time.Duration {
|
|
||||||
r, _, _ := _GetMessageTime.Call()
|
|
||||||
return time.Duration(r) * time.Millisecond
|
|
||||||
}
|
|
||||||
|
|
||||||
func killTimer(hwnd syscall.Handle, nIDEvent uintptr) error {
|
|
||||||
r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), 0, 0)
|
|
||||||
if r == 0 {
|
|
||||||
return fmt.Errorf("KillTimer failed: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadCursor(curID uint16) (syscall.Handle, error) {
|
|
||||||
h, _, err := _LoadCursor.Call(0, uintptr(curID))
|
|
||||||
if h == 0 {
|
|
||||||
return 0, fmt.Errorf("LoadCursorW failed: %v", err)
|
|
||||||
}
|
|
||||||
return syscall.Handle(h), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func monitorFromPoint(pt point, flags uint32) syscall.Handle {
|
|
||||||
r, _, _ := _MonitorFromPoint.Call(uintptr(pt.x), uintptr(pt.y), uintptr(flags))
|
|
||||||
return syscall.Handle(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func msgWaitForMultipleObjectsEx(nCount uint32, pHandles uintptr, millis, mask, flags uint32) (uint32, error) {
|
|
||||||
r, _, err := _MsgWaitForMultipleObjectsEx.Call(uintptr(nCount), pHandles, uintptr(millis), uintptr(mask), uintptr(flags))
|
|
||||||
res := uint32(r)
|
|
||||||
if res == 0xFFFFFFFF {
|
|
||||||
return 0, fmt.Errorf("MsgWaitForMultipleObjectsEx failed: %v", err)
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func peekMessage(m *msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool {
|
|
||||||
r, _, _ := _PeekMessage.Call(uintptr(unsafe.Pointer(m)), uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), uintptr(wRemoveMsg))
|
|
||||||
issue34474KeepAlive(m)
|
|
||||||
return r != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func postQuitMessage(exitCode uintptr) {
|
|
||||||
_PostQuitMessage.Call(exitCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func postMessage(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) error {
|
|
||||||
r, _, err := _PostMessage.Call(uintptr(hwnd), uintptr(msg), wParam, lParam)
|
|
||||||
if r == 0 {
|
|
||||||
return fmt.Errorf("PostMessage failed: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func releaseCapture() bool {
|
|
||||||
r, _, _ := _ReleaseCapture.Call()
|
|
||||||
return r != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func registerClassEx(cls *wndClassEx) (uint16, error) {
|
|
||||||
a, _, err := _RegisterClassExW.Call(uintptr(unsafe.Pointer(cls)))
|
|
||||||
issue34474KeepAlive(cls)
|
|
||||||
if a == 0 {
|
|
||||||
return 0, fmt.Errorf("RegisterClassExW failed: %v", err)
|
|
||||||
}
|
|
||||||
return uint16(a), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func releaseDC(hdc syscall.Handle) {
|
|
||||||
_ReleaseDC.Call(uintptr(hdc))
|
|
||||||
}
|
|
||||||
|
|
||||||
func setForegroundWindow(hwnd syscall.Handle) {
|
|
||||||
_SetForegroundWindow.Call(uintptr(hwnd))
|
|
||||||
}
|
|
||||||
|
|
||||||
func setFocus(hwnd syscall.Handle) {
|
|
||||||
_SetFocus.Call(uintptr(hwnd))
|
|
||||||
}
|
|
||||||
|
|
||||||
func setProcessDPIAware() {
|
|
||||||
_SetProcessDPIAware.Call()
|
|
||||||
}
|
|
||||||
|
|
||||||
func setCapture(hwnd syscall.Handle) syscall.Handle {
|
|
||||||
r, _, _ := _SetCapture.Call(uintptr(hwnd))
|
|
||||||
return syscall.Handle(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func setTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc uintptr) error {
|
|
||||||
r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), uintptr(uElapse), timerProc)
|
|
||||||
if r == 0 {
|
|
||||||
return fmt.Errorf("SetTimer failed: %v", err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func screenToClient(hwnd syscall.Handle, p *point) {
|
|
||||||
_ScreenToClient.Call(uintptr(hwnd), uintptr(unsafe.Pointer(p)))
|
|
||||||
issue34474KeepAlive(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func showWindow(hwnd syscall.Handle, nCmdShow int32) {
|
|
||||||
_ShowWindow.Call(uintptr(hwnd), uintptr(nCmdShow))
|
|
||||||
}
|
|
||||||
|
|
||||||
func translateMessage(m *msg) {
|
|
||||||
_TranslateMessage.Call(uintptr(unsafe.Pointer(m)))
|
|
||||||
issue34474KeepAlive(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func unregisterClass(cls uint16, hInst syscall.Handle) {
|
|
||||||
_UnregisterClass.Call(uintptr(cls), uintptr(hInst))
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateWindow(hwnd syscall.Handle) {
|
|
||||||
_UpdateWindow.Call(uintptr(hwnd))
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue34474KeepAlive calls runtime.KeepAlive as a
|
|
||||||
// workaround for golang.org/issue/34474.
|
|
||||||
func issue34474KeepAlive(v interface{}) {
|
|
||||||
runtime.KeepAlive(v)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -0,0 +1,450 @@
|
|||||||
|
// SPDX-License-Identifier: Unlicense OR MIT
|
||||||
|
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package windows
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
"time"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
syscall "golang.org/x/sys/windows"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Rect struct {
|
||||||
|
Left, Top, Right, Bottom int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type WndClassEx struct {
|
||||||
|
CbSize uint32
|
||||||
|
Style uint32
|
||||||
|
LpfnWndProc uintptr
|
||||||
|
CnClsExtra int32
|
||||||
|
CbWndExtra int32
|
||||||
|
HInstance syscall.Handle
|
||||||
|
HIcon syscall.Handle
|
||||||
|
HCursor syscall.Handle
|
||||||
|
HbrBackground syscall.Handle
|
||||||
|
LpszMenuName *uint16
|
||||||
|
LpszClassName *uint16
|
||||||
|
HIconSm syscall.Handle
|
||||||
|
}
|
||||||
|
|
||||||
|
type Msg struct {
|
||||||
|
Hwnd syscall.Handle
|
||||||
|
Message uint32
|
||||||
|
WParam uintptr
|
||||||
|
LParam uintptr
|
||||||
|
Time uint32
|
||||||
|
Pt Point
|
||||||
|
LPrivate uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type Point struct {
|
||||||
|
X, Y int32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
CS_HREDRAW = 0x0002
|
||||||
|
CS_VREDRAW = 0x0001
|
||||||
|
CS_OWNDC = 0x0020
|
||||||
|
|
||||||
|
CW_USEDEFAULT = -2147483648
|
||||||
|
|
||||||
|
IDC_ARROW = 32512
|
||||||
|
|
||||||
|
INFINITE = 0xFFFFFFFF
|
||||||
|
|
||||||
|
LOGPIXELSX = 88
|
||||||
|
|
||||||
|
MDT_EFFECTIVE_DPI = 0
|
||||||
|
|
||||||
|
MONITOR_DEFAULTTOPRIMARY = 1
|
||||||
|
|
||||||
|
SIZE_MAXIMIZED = 2
|
||||||
|
SIZE_MINIMIZED = 1
|
||||||
|
SIZE_RESTORED = 0
|
||||||
|
|
||||||
|
SW_SHOWDEFAULT = 10
|
||||||
|
|
||||||
|
USER_TIMER_MINIMUM = 0x0000000A
|
||||||
|
|
||||||
|
VK_CONTROL = 0x11
|
||||||
|
VK_LWIN = 0x5B
|
||||||
|
VK_MENU = 0x12
|
||||||
|
VK_RWIN = 0x5C
|
||||||
|
VK_SHIFT = 0x10
|
||||||
|
|
||||||
|
VK_BACK = 0x08
|
||||||
|
VK_DELETE = 0x2e
|
||||||
|
VK_DOWN = 0x28
|
||||||
|
VK_END = 0x23
|
||||||
|
VK_ESCAPE = 0x1b
|
||||||
|
VK_HOME = 0x24
|
||||||
|
VK_LEFT = 0x25
|
||||||
|
VK_NEXT = 0x22
|
||||||
|
VK_PRIOR = 0x21
|
||||||
|
VK_RIGHT = 0x27
|
||||||
|
VK_RETURN = 0x0d
|
||||||
|
VK_SPACE = 0x20
|
||||||
|
VK_TAB = 0x09
|
||||||
|
VK_UP = 0x26
|
||||||
|
|
||||||
|
VK_F1 = 0x70
|
||||||
|
VK_F2 = 0x71
|
||||||
|
VK_F3 = 0x72
|
||||||
|
VK_F4 = 0x73
|
||||||
|
VK_F5 = 0x74
|
||||||
|
VK_F6 = 0x75
|
||||||
|
VK_F7 = 0x76
|
||||||
|
VK_F8 = 0x77
|
||||||
|
VK_F9 = 0x78
|
||||||
|
VK_F10 = 0x79
|
||||||
|
VK_F11 = 0x7A
|
||||||
|
VK_F12 = 0x7B
|
||||||
|
|
||||||
|
VK_OEM_1 = 0xba
|
||||||
|
VK_OEM_PLUS = 0xbb
|
||||||
|
VK_OEM_COMMA = 0xbc
|
||||||
|
VK_OEM_MINUS = 0xbd
|
||||||
|
VK_OEM_PERIOD = 0xbe
|
||||||
|
VK_OEM_2 = 0xbf
|
||||||
|
VK_OEM_3 = 0xc0
|
||||||
|
VK_OEM_4 = 0xdb
|
||||||
|
VK_OEM_5 = 0xdc
|
||||||
|
VK_OEM_6 = 0xdd
|
||||||
|
VK_OEM_7 = 0xde
|
||||||
|
VK_OEM_102 = 0xe2
|
||||||
|
|
||||||
|
UNICODE_NOCHAR = 65535
|
||||||
|
|
||||||
|
WM_CANCELMODE = 0x001F
|
||||||
|
WM_CHAR = 0x0102
|
||||||
|
WM_CREATE = 0x0001
|
||||||
|
WM_DPICHANGED = 0x02E0
|
||||||
|
WM_DESTROY = 0x0002
|
||||||
|
WM_ERASEBKGND = 0x0014
|
||||||
|
WM_KEYDOWN = 0x0100
|
||||||
|
WM_KEYUP = 0x0101
|
||||||
|
WM_LBUTTONDOWN = 0x0201
|
||||||
|
WM_LBUTTONUP = 0x0202
|
||||||
|
WM_MBUTTONDOWN = 0x0207
|
||||||
|
WM_MBUTTONUP = 0x0208
|
||||||
|
WM_MOUSEMOVE = 0x0200
|
||||||
|
WM_MOUSEWHEEL = 0x020A
|
||||||
|
WM_PAINT = 0x000F
|
||||||
|
WM_QUIT = 0x0012
|
||||||
|
WM_SETFOCUS = 0x0007
|
||||||
|
WM_KILLFOCUS = 0x0008
|
||||||
|
WM_SHOWWINDOW = 0x0018
|
||||||
|
WM_SIZE = 0x0005
|
||||||
|
WM_SYSKEYDOWN = 0x0104
|
||||||
|
WM_RBUTTONDOWN = 0x0204
|
||||||
|
WM_RBUTTONUP = 0x0205
|
||||||
|
WM_TIMER = 0x0113
|
||||||
|
WM_UNICHAR = 0x0109
|
||||||
|
WM_USER = 0x0400
|
||||||
|
|
||||||
|
WS_CLIPCHILDREN = 0x00010000
|
||||||
|
WS_CLIPSIBLINGS = 0x04000000
|
||||||
|
WS_VISIBLE = 0x10000000
|
||||||
|
WS_OVERLAPPED = 0x00000000
|
||||||
|
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
|
||||||
|
WS_MINIMIZEBOX | WS_MAXIMIZEBOX
|
||||||
|
WS_CAPTION = 0x00C00000
|
||||||
|
WS_SYSMENU = 0x00080000
|
||||||
|
WS_THICKFRAME = 0x00040000
|
||||||
|
WS_MINIMIZEBOX = 0x00020000
|
||||||
|
WS_MAXIMIZEBOX = 0x00010000
|
||||||
|
|
||||||
|
WS_EX_APPWINDOW = 0x00040000
|
||||||
|
WS_EX_WINDOWEDGE = 0x00000100
|
||||||
|
|
||||||
|
QS_ALLINPUT = 0x04FF
|
||||||
|
|
||||||
|
MWMO_WAITALL = 0x0001
|
||||||
|
MWMO_INPUTAVAILABLE = 0x0004
|
||||||
|
|
||||||
|
WAIT_OBJECT_0 = 0
|
||||||
|
|
||||||
|
PM_REMOVE = 0x0001
|
||||||
|
PM_NOREMOVE = 0x0000
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
kernel32 = syscall.NewLazySystemDLL("kernel32.dll")
|
||||||
|
_GetModuleHandleW = kernel32.NewProc("GetModuleHandleW")
|
||||||
|
|
||||||
|
user32 = syscall.NewLazySystemDLL("user32.dll")
|
||||||
|
_AdjustWindowRectEx = user32.NewProc("AdjustWindowRectEx")
|
||||||
|
_CallMsgFilter = user32.NewProc("CallMsgFilterW")
|
||||||
|
_CreateWindowEx = user32.NewProc("CreateWindowExW")
|
||||||
|
_DefWindowProc = user32.NewProc("DefWindowProcW")
|
||||||
|
_DestroyWindow = user32.NewProc("DestroyWindow")
|
||||||
|
_DispatchMessage = user32.NewProc("DispatchMessageW")
|
||||||
|
_GetClientRect = user32.NewProc("GetClientRect")
|
||||||
|
_GetDC = user32.NewProc("GetDC")
|
||||||
|
_GetKeyState = user32.NewProc("GetKeyState")
|
||||||
|
_GetMessage = user32.NewProc("GetMessageW")
|
||||||
|
_GetMessageTime = user32.NewProc("GetMessageTime")
|
||||||
|
_KillTimer = user32.NewProc("KillTimer")
|
||||||
|
_LoadCursor = user32.NewProc("LoadCursorW")
|
||||||
|
_MonitorFromPoint = user32.NewProc("MonitorFromPoint")
|
||||||
|
_MsgWaitForMultipleObjectsEx = user32.NewProc("MsgWaitForMultipleObjectsEx")
|
||||||
|
_PeekMessage = user32.NewProc("PeekMessageW")
|
||||||
|
_PostMessage = user32.NewProc("PostMessageW")
|
||||||
|
_PostQuitMessage = user32.NewProc("PostQuitMessage")
|
||||||
|
_ReleaseCapture = user32.NewProc("ReleaseCapture")
|
||||||
|
_RegisterClassExW = user32.NewProc("RegisterClassExW")
|
||||||
|
_ReleaseDC = user32.NewProc("ReleaseDC")
|
||||||
|
_ScreenToClient = user32.NewProc("ScreenToClient")
|
||||||
|
_ShowWindow = user32.NewProc("ShowWindow")
|
||||||
|
_SetCapture = user32.NewProc("SetCapture")
|
||||||
|
_SetForegroundWindow = user32.NewProc("SetForegroundWindow")
|
||||||
|
_SetFocus = user32.NewProc("SetFocus")
|
||||||
|
_SetProcessDPIAware = user32.NewProc("SetProcessDPIAware")
|
||||||
|
_SetTimer = user32.NewProc("SetTimer")
|
||||||
|
_TranslateMessage = user32.NewProc("TranslateMessage")
|
||||||
|
_UnregisterClass = user32.NewProc("UnregisterClassW")
|
||||||
|
_UpdateWindow = user32.NewProc("UpdateWindow")
|
||||||
|
|
||||||
|
shcore = syscall.NewLazySystemDLL("shcore")
|
||||||
|
_GetDpiForMonitor = shcore.NewProc("GetDpiForMonitor")
|
||||||
|
|
||||||
|
gdi32 = syscall.NewLazySystemDLL("gdi32")
|
||||||
|
_GetDeviceCaps = gdi32.NewProc("GetDeviceCaps")
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetModuleHandle() (syscall.Handle, error) {
|
||||||
|
h, _, err := _GetModuleHandleW.Call(uintptr(0))
|
||||||
|
if h == 0 {
|
||||||
|
return 0, fmt.Errorf("GetModuleHandleW failed: %v", err)
|
||||||
|
}
|
||||||
|
return syscall.Handle(h), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AdjustWindowRectEx(r *Rect, dwStyle uint32, bMenu int, dwExStyle uint32) {
|
||||||
|
_AdjustWindowRectEx.Call(uintptr(unsafe.Pointer(r)), uintptr(dwStyle), uintptr(bMenu), uintptr(dwExStyle))
|
||||||
|
issue34474KeepAlive(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CallMsgFilter(m *Msg, nCode uintptr) bool {
|
||||||
|
r, _, _ := _CallMsgFilter.Call(uintptr(unsafe.Pointer(m)), nCode)
|
||||||
|
issue34474KeepAlive(m)
|
||||||
|
return r != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateWindowEx(dwExStyle uint32, lpClassName uint16, lpWindowName string, dwStyle uint32, x, y, w, h int32, hWndParent, hMenu, hInstance syscall.Handle, lpParam uintptr) (syscall.Handle, error) {
|
||||||
|
wname := syscall.StringToUTF16Ptr(lpWindowName)
|
||||||
|
hwnd, _, err := _CreateWindowEx.Call(
|
||||||
|
uintptr(dwExStyle),
|
||||||
|
uintptr(lpClassName),
|
||||||
|
uintptr(unsafe.Pointer(wname)),
|
||||||
|
uintptr(dwStyle),
|
||||||
|
uintptr(x), uintptr(y),
|
||||||
|
uintptr(w), uintptr(h),
|
||||||
|
uintptr(hWndParent),
|
||||||
|
uintptr(hMenu),
|
||||||
|
uintptr(hInstance),
|
||||||
|
uintptr(lpParam))
|
||||||
|
issue34474KeepAlive(wname)
|
||||||
|
if hwnd == 0 {
|
||||||
|
return 0, fmt.Errorf("CreateWindowEx failed: %v", err)
|
||||||
|
}
|
||||||
|
return syscall.Handle(hwnd), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefWindowProc(hwnd syscall.Handle, msg uint32, wparam, lparam uintptr) uintptr {
|
||||||
|
r, _, _ := _DefWindowProc.Call(uintptr(hwnd), uintptr(msg), wparam, lparam)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func DestroyWindow(hwnd syscall.Handle) {
|
||||||
|
_DestroyWindow.Call(uintptr(hwnd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func DispatchMessage(m *Msg) {
|
||||||
|
_DispatchMessage.Call(uintptr(unsafe.Pointer(m)))
|
||||||
|
issue34474KeepAlive(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetClientRect(hwnd syscall.Handle, r *Rect) {
|
||||||
|
_GetClientRect.Call(uintptr(hwnd), uintptr(unsafe.Pointer(r)))
|
||||||
|
issue34474KeepAlive(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDC(hwnd syscall.Handle) (syscall.Handle, error) {
|
||||||
|
hdc, _, err := _GetDC.Call(uintptr(hwnd))
|
||||||
|
if hdc == 0 {
|
||||||
|
return 0, fmt.Errorf("GetDC failed: %v", err)
|
||||||
|
}
|
||||||
|
return syscall.Handle(hdc), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDeviceCaps(hdc syscall.Handle, index int32) int {
|
||||||
|
c, _, _ := _GetDeviceCaps.Call(uintptr(hdc), uintptr(index))
|
||||||
|
return int(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDpiForMonitor(hmonitor syscall.Handle, dpiType uint32) int {
|
||||||
|
var dpiX, dpiY uintptr
|
||||||
|
_GetDpiForMonitor.Call(uintptr(hmonitor), uintptr(dpiType), uintptr(unsafe.Pointer(&dpiX)), uintptr(unsafe.Pointer(&dpiY)))
|
||||||
|
return int(dpiX)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSystemDPI returns the effective DPI of the system.
|
||||||
|
func GetSystemDPI() int {
|
||||||
|
// Check for getDpiForMonitor, introduced in Windows 8.1.
|
||||||
|
if _GetDpiForMonitor.Find() == nil {
|
||||||
|
hmon := monitorFromPoint(Point{}, MONITOR_DEFAULTTOPRIMARY)
|
||||||
|
return getDpiForMonitor(hmon, MDT_EFFECTIVE_DPI)
|
||||||
|
} else {
|
||||||
|
// Fall back to the physical device DPI.
|
||||||
|
screenDC, err := GetDC(0)
|
||||||
|
if err != nil {
|
||||||
|
return 96
|
||||||
|
}
|
||||||
|
defer ReleaseDC(screenDC)
|
||||||
|
return getDeviceCaps(screenDC, LOGPIXELSX)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetKeyState(nVirtKey int32) int16 {
|
||||||
|
c, _, _ := _GetKeyState.Call(uintptr(nVirtKey))
|
||||||
|
return int16(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax uint32) int32 {
|
||||||
|
r, _, _ := _GetMessage.Call(uintptr(unsafe.Pointer(m)),
|
||||||
|
uintptr(hwnd),
|
||||||
|
uintptr(wMsgFilterMin),
|
||||||
|
uintptr(wMsgFilterMax))
|
||||||
|
issue34474KeepAlive(m)
|
||||||
|
return int32(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMessageTime() time.Duration {
|
||||||
|
r, _, _ := _GetMessageTime.Call()
|
||||||
|
return time.Duration(r) * time.Millisecond
|
||||||
|
}
|
||||||
|
|
||||||
|
func KillTimer(hwnd syscall.Handle, nIDEvent uintptr) error {
|
||||||
|
r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), 0, 0)
|
||||||
|
if r == 0 {
|
||||||
|
return fmt.Errorf("KillTimer failed: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadCursor(curID uint16) (syscall.Handle, error) {
|
||||||
|
h, _, err := _LoadCursor.Call(0, uintptr(curID))
|
||||||
|
if h == 0 {
|
||||||
|
return 0, fmt.Errorf("LoadCursorW failed: %v", err)
|
||||||
|
}
|
||||||
|
return syscall.Handle(h), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func monitorFromPoint(pt Point, flags uint32) syscall.Handle {
|
||||||
|
r, _, _ := _MonitorFromPoint.Call(uintptr(pt.X), uintptr(pt.Y), uintptr(flags))
|
||||||
|
return syscall.Handle(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func MsgWaitForMultipleObjectsEx(nCount uint32, pHandles uintptr, millis, mask, flags uint32) (uint32, error) {
|
||||||
|
r, _, err := _MsgWaitForMultipleObjectsEx.Call(uintptr(nCount), pHandles, uintptr(millis), uintptr(mask), uintptr(flags))
|
||||||
|
res := uint32(r)
|
||||||
|
if res == 0xFFFFFFFF {
|
||||||
|
return 0, fmt.Errorf("MsgWaitForMultipleObjectsEx failed: %v", err)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func PeekMessage(m *Msg, hwnd syscall.Handle, wMsgFilterMin, wMsgFilterMax, wRemoveMsg uint32) bool {
|
||||||
|
r, _, _ := _PeekMessage.Call(uintptr(unsafe.Pointer(m)), uintptr(hwnd), uintptr(wMsgFilterMin), uintptr(wMsgFilterMax), uintptr(wRemoveMsg))
|
||||||
|
issue34474KeepAlive(m)
|
||||||
|
return r != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostQuitMessage(exitCode uintptr) {
|
||||||
|
_PostQuitMessage.Call(exitCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostMessage(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) error {
|
||||||
|
r, _, err := _PostMessage.Call(uintptr(hwnd), uintptr(msg), wParam, lParam)
|
||||||
|
if r == 0 {
|
||||||
|
return fmt.Errorf("PostMessage failed: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReleaseCapture() bool {
|
||||||
|
r, _, _ := _ReleaseCapture.Call()
|
||||||
|
return r != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterClassEx(cls *WndClassEx) (uint16, error) {
|
||||||
|
a, _, err := _RegisterClassExW.Call(uintptr(unsafe.Pointer(cls)))
|
||||||
|
issue34474KeepAlive(cls)
|
||||||
|
if a == 0 {
|
||||||
|
return 0, fmt.Errorf("RegisterClassExW failed: %v", err)
|
||||||
|
}
|
||||||
|
return uint16(a), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReleaseDC(hdc syscall.Handle) {
|
||||||
|
_ReleaseDC.Call(uintptr(hdc))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetForegroundWindow(hwnd syscall.Handle) {
|
||||||
|
_SetForegroundWindow.Call(uintptr(hwnd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetFocus(hwnd syscall.Handle) {
|
||||||
|
_SetFocus.Call(uintptr(hwnd))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetProcessDPIAware() {
|
||||||
|
_SetProcessDPIAware.Call()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCapture(hwnd syscall.Handle) syscall.Handle {
|
||||||
|
r, _, _ := _SetCapture.Call(uintptr(hwnd))
|
||||||
|
return syscall.Handle(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetTimer(hwnd syscall.Handle, nIDEvent uintptr, uElapse uint32, timerProc uintptr) error {
|
||||||
|
r, _, err := _SetTimer.Call(uintptr(hwnd), uintptr(nIDEvent), uintptr(uElapse), timerProc)
|
||||||
|
if r == 0 {
|
||||||
|
return fmt.Errorf("SetTimer failed: %v", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScreenToClient(hwnd syscall.Handle, p *Point) {
|
||||||
|
_ScreenToClient.Call(uintptr(hwnd), uintptr(unsafe.Pointer(p)))
|
||||||
|
issue34474KeepAlive(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ShowWindow(hwnd syscall.Handle, nCmdShow int32) {
|
||||||
|
_ShowWindow.Call(uintptr(hwnd), uintptr(nCmdShow))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TranslateMessage(m *Msg) {
|
||||||
|
_TranslateMessage.Call(uintptr(unsafe.Pointer(m)))
|
||||||
|
issue34474KeepAlive(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnregisterClass(cls uint16, hInst syscall.Handle) {
|
||||||
|
_UnregisterClass.Call(uintptr(cls), uintptr(hInst))
|
||||||
|
}
|
||||||
|
|
||||||
|
func UpdateWindow(hwnd syscall.Handle) {
|
||||||
|
_UpdateWindow.Call(uintptr(hwnd))
|
||||||
|
}
|
||||||
|
|
||||||
|
// issue34474KeepAlive calls runtime.KeepAlive as a
|
||||||
|
// workaround for golang.org/issue/34474.
|
||||||
|
func issue34474KeepAlive(v interface{}) {
|
||||||
|
runtime.KeepAlive(v)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user