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)) }