TTW_Bot_GO/internal/hotkey/hotkey_windows.go

120 lines
2.9 KiB
Go

package hotkey
import (
"fmt"
"runtime"
"strings"
"syscall"
"unsafe"
)
var (
user32 = syscall.NewLazyDLL("user32.dll")
procSendInput = user32.NewProc("SendInput")
)
const (
INPUT_KEYBOARD = 1
KEYEVENTF_KEYDOWN = 0x0000
KEYEVENTF_KEYUP = 0x0002
)
type INPUT struct {
Type uint32
Ki KEYBDINPUT
}
type KEYBDINPUT struct {
WVirtKey uint16
WScan uint16
DwFlags uint32
Time uint32
DwExtra uint32
}
// Виртуальные коды клавиш
var keyCodes = map[string]uint16{
"A": 0x41, "B": 0x42, "C": 0x43, "D": 0x44, "E": 0x45, "F": 0x46, "G": 0x47, "H": 0x48,
"I": 0x49, "J": 0x4A, "K": 0x4B, "L": 0x4C, "M": 0x4D, "N": 0x4E, "O": 0x4F, "P": 0x50,
"Q": 0x51, "R": 0x52, "S": 0x53, "T": 0x54, "U": 0x55, "V": 0x56, "W": 0x57, "X": 0x58,
"Y": 0x59, "Z": 0x5A,
"0": 0x30, "1": 0x31, "2": 0x32, "3": 0x33, "4": 0x34, "5": 0x35, "6": 0x36, "7": 0x37, "8": 0x38, "9": 0x39,
"F1": 0x70, "F2": 0x71, "F3": 0x72, "F4": 0x73, "F5": 0x74, "F6": 0x75, "F7": 0x76, "F8": 0x77,
"F9": 0x78, "F10": 0x79, "F11": 0x7A, "F12": 0x7B,
"SPACE": 0x20, "ENTER": 0x0D, "TAB": 0x09, "ESC": 0x1B,
"SHIFT": 0x10, "CTRL": 0x11, "ALT": 0x12, "WIN": 0x5B,
"LEFT": 0x25, "UP": 0x26, "RIGHT": 0x27, "DOWN": 0x28,
}
var modCodes = map[string]uint16{
"ALT": 0x12,
"CTRL": 0x11,
"SHIFT": 0x10,
"WIN": 0x5B,
}
var enabled bool = false
func Init() error {
if runtime.GOOS != "windows" {
return fmt.Errorf("hotkey emulation only supported on Windows")
}
enabled = true
return nil
}
func SetEnabled(e bool) {
enabled = e
}
func PressCombination(combination string) error {
if !enabled {
return fmt.Errorf("hotkey emulation disabled by user")
}
parts := strings.Split(combination, "+")
if len(parts) == 0 {
return fmt.Errorf("invalid combination")
}
var mods []uint16
var mainKey uint16
for _, p := range parts {
upper := strings.ToUpper(p)
if code, ok := modCodes[upper]; ok {
mods = append(mods, code)
} else if code, ok := keyCodes[upper]; ok {
mainKey = code
} else {
return fmt.Errorf("unknown key: %s", p)
}
}
if mainKey == 0 {
return fmt.Errorf("no main key found")
}
for _, mod := range mods {
pressKey(mod, true)
}
pressKey(mainKey, true)
pressKey(mainKey, false)
for i := len(mods) - 1; i >= 0; i-- {
pressKey(mods[i], false)
}
return nil
}
func pressKey(vk uint16, down bool) {
var flags uint32 = KEYEVENTF_KEYDOWN
if !down {
flags = KEYEVENTF_KEYUP
}
input := INPUT{
Type: INPUT_KEYBOARD,
Ki: KEYBDINPUT{
WVirtKey: vk,
DwFlags: flags,
},
}
procSendInput.Call(1, uintptr(unsafe.Pointer(&input)), unsafe.Sizeof(input))
}