-
Notifications
You must be signed in to change notification settings - Fork 0
/
keypresses.go
93 lines (82 loc) · 2.24 KB
/
keypresses.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package keypresses
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var (
mod = windows.NewLazyDLL("user32.dll")
procGetClassNameW = mod.NewProc("GetClassNameW")
procGetAsyncKeyState = mod.NewProc("GetAsyncKeyState")
classtolook = []string{
"ConsoleWindowClass",
}
)
type (
HANDLE uintptr
HWND HANDLE
)
func getClassName(hwnd HWND) (name string, err error) {
n := make([]uint16, 256)
p := &n[0]
r0, _, e1 := syscall.Syscall(procGetClassNameW.Addr(), 3, uintptr(hwnd), uintptr(unsafe.Pointer(p)), uintptr(len(n)))
if r0 == 0 {
if e1 != 0 {
err = error(e1)
} else {
err = syscall.EINVAL
}
return
}
name = syscall.UTF16ToString(n)
return
}
func getWindow(funcName string) uintptr {
proc := mod.NewProc(funcName)
hwnd, _, _ := proc.Call()
return hwnd
}
func checkInArray(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
/*
With IsKeyPressedGlobal you can get key state only if current window is active.
keyVirtualCode - win32api virtual code, you can get more info about it on microsoft win api documentation.
"false" argument means that to get key state, window should be active.
"true" argument means that to get key state, window might not be active, the same as an IsKeyPressed function.
*/
func IsKeyPressedGlobal(keyVirtualCode int, global bool) bool {
if global {
return IsKeyPressed(keyVirtualCode)
}
if hwnd := getWindow("GetForegroundWindow"); hwnd != 0 {
cn, _ := getClassName(HWND(hwnd))
if checkInArray(cn, classtolook) {
return IsKeyPressed(keyVirtualCode)
}
return false
}
return false
}
/*
Getting key state (even if window inactive).
keyVirtualCode - win32api virtual code, you can more info about it on microsoft win api documentation.
*/
func IsKeyPressed(keyVirtualCode int) bool {
// Query key mapped to integer `0x00` to `0xFF` if it's pressed.
asynch, _, _ := procGetAsyncKeyState.Call(uintptr(keyVirtualCode))
// If the least significant bit is set ignore it.
//
// As it's written in the documentation:
// `if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.`
// Which we don't care about :)
if asynch&0x1 == 0 {
return false
}
return true
}