Files

117 lines
2.5 KiB
Go
Raw Permalink Normal View History

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
}