117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package input
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"syscall"
|
|
"unicode/utf16"
|
|
"unsafe"
|
|
)
|
|
|
|
const (
|
|
inputMouse = 0
|
|
inputKeyboard = 1
|
|
|
|
mouseLeftDown = 0x0002
|
|
mouseLeftUp = 0x0004
|
|
mouseRightDown = 0x0008
|
|
mouseRightUp = 0x0010
|
|
|
|
keyeventfKeyup = 0x0002
|
|
keyeventfUnicode = 0x0004
|
|
)
|
|
|
|
var (
|
|
ErrBadButton = errors.New("button must be left or right")
|
|
ErrEmptyText = errors.New("text must not be empty")
|
|
|
|
user32 = syscall.NewLazyDLL("user32.dll")
|
|
procSetCursorPos = user32.NewProc("SetCursorPos")
|
|
procSendInput = user32.NewProc("SendInput")
|
|
procSetProcessDPIAware = user32.NewProc("SetProcessDPIAware")
|
|
)
|
|
|
|
type mouseInput struct {
|
|
Type uint32
|
|
_ uint32
|
|
Dx int32
|
|
Dy int32
|
|
MouseData uint32
|
|
Flags uint32
|
|
Time uint32
|
|
ExtraInfo uintptr
|
|
}
|
|
|
|
type keybdInput struct {
|
|
Type uint32
|
|
_ uint32
|
|
Vk uint16
|
|
Scan uint16
|
|
Flags uint32
|
|
Time uint32
|
|
ExtraInfo uintptr
|
|
_ [8]byte
|
|
}
|
|
|
|
func EnableDPIAwareness() {
|
|
_, _, _ = procSetProcessDPIAware.Call()
|
|
}
|
|
|
|
func Click(x, y int, button string) error {
|
|
down, up, err := mouseFlags(button)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
ok, _, callErr := procSetCursorPos.Call(uintptr(x), uintptr(y))
|
|
if ok == 0 {
|
|
return callErr
|
|
}
|
|
inputs := []mouseInput{
|
|
{Type: inputMouse, Flags: down},
|
|
{Type: inputMouse, Flags: up},
|
|
}
|
|
return sendMouse(inputs)
|
|
}
|
|
|
|
func TypeText(text string) error {
|
|
if text == "" {
|
|
return ErrEmptyText
|
|
}
|
|
units := utf16.Encode([]rune(text))
|
|
inputs := make([]keybdInput, 0, len(units)*2)
|
|
for _, unit := range units {
|
|
inputs = append(inputs,
|
|
keybdInput{Type: inputKeyboard, Scan: unit, Flags: keyeventfUnicode},
|
|
keybdInput{Type: inputKeyboard, Scan: unit, Flags: keyeventfUnicode | keyeventfKeyup},
|
|
)
|
|
}
|
|
return sendKeys(inputs)
|
|
}
|
|
|
|
func mouseFlags(button string) (down, up uint32, err error) {
|
|
switch strings.ToLower(strings.TrimSpace(button)) {
|
|
case "", "left":
|
|
return mouseLeftDown, mouseLeftUp, nil
|
|
case "right":
|
|
return mouseRightDown, mouseRightUp, nil
|
|
default:
|
|
return 0, 0, ErrBadButton
|
|
}
|
|
}
|
|
|
|
func sendMouse(inputs []mouseInput) error {
|
|
n, _, err := procSendInput.Call(uintptr(len(inputs)), uintptr(unsafe.Pointer(&inputs[0])), uintptr(unsafe.Sizeof(inputs[0])))
|
|
if n == 0 {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func sendKeys(inputs []keybdInput) error {
|
|
n, _, err := procSendInput.Call(uintptr(len(inputs)), uintptr(unsafe.Pointer(&inputs[0])), uintptr(unsafe.Sizeof(inputs[0])))
|
|
if n == 0 {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|