Skip to content

Instantly share code, notes, and snippets.

@jordansissel
Forked from obonyojimmy/keyboardcapture.go
Created September 26, 2017 05:08
Show Gist options
  • Save jordansissel/1e08b1c65157bde0f30a87c4fb569237 to your computer and use it in GitHub Desktop.
Save jordansissel/1e08b1c65157bde0f30a87c4fb569237 to your computer and use it in GitHub Desktop.
go lang keyboard capture
package main
import (
"fmt"
"syscall"
//~ "time"
"unsafe"
"golang.org/x/sys/windows"
)
// String returns a human-friendly display name of the hotkey
// such as "Hotkey[Id: 1, Alt+Ctrl+O]"
var (
user32 = windows.NewLazySystemDLL("user32.dll")
procSetWindowsHookEx = user32.NewProc("SetWindowsHookEx")
procLowLevelKeyboard = user32.NewProc("LowLevelKeyboardProc")
procCallNextHookEx = user32.NewProc("CallNextHookEx")
procUnhookWindowsHookEx = user32.NewProc("UnhookWindowsHookEx")
procGetMessage = user32.NewProc("GetMessageW")
procTranslateMessage = user32.NewProc("TranslateMessage")
procDispatchMessage = user32.NewProc("DispatchMessageW")
keyboardHook HHOOK
)
const (
WH_KEYBOARD_LL = 13
WH_KEYBOARD = 2
WM_KEYDOWN = 256
WM_SYSKEYDOWN = 260
WM_KEYUP = 257
WM_SYSKEYUP = 261
WM_KEYFIRST = 256
WM_KEYLAST = 264
PM_NOREMOVE = 0x000
PM_REMOVE = 0x001
PM_NOYIELD = 0x002
WM_LBUTTONDOWN = 513
WM_RBUTTONDOWN = 516
NULL = 0
)
type (
DWORD uint32
WPARAM uintptr
LPARAM uintptr
LRESULT uintptr
HANDLE uintptr
HINSTANCE HANDLE
HHOOK HANDLE
HWND HANDLE
)
type HOOKPROC func(int, WPARAM, LPARAM) LRESULT
type KBDLLHOOKSTRUCT struct {
VkCode DWORD
ScanCode DWORD
Flags DWORD
Time DWORD
DwExtraInfo uintptr
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/dd162805.aspx
type POINT struct {
X, Y int32
}
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms644958.aspx
type MSG struct {
Hwnd HWND
Message uint32
WParam uintptr
LParam uintptr
Time uint32
Pt POINT
}
func SetWindowsHookEx(idHook int, lpfn HOOKPROC, hMod HINSTANCE, dwThreadId DWORD) HHOOK {
ret, _, _ := procSetWindowsHookEx.Call(
uintptr(idHook),
uintptr(syscall.NewCallback(lpfn)),
uintptr(hMod),
uintptr(dwThreadId),
)
return HHOOK(ret)
}
func CallNextHookEx(hhk HHOOK, nCode int, wParam WPARAM, lParam LPARAM) LRESULT {
ret, _, _ := procCallNextHookEx.Call(
uintptr(hhk),
uintptr(nCode),
uintptr(wParam),
uintptr(lParam),
)
return LRESULT(ret)
}
func UnhookWindowsHookEx(hhk HHOOK) bool {
ret, _, _ := procUnhookWindowsHookEx.Call(
uintptr(hhk),
)
return ret != 0
}
func GetMessage(msg *MSG, hwnd HWND, msgFilterMin uint32, msgFilterMax uint32) int {
ret, _, _ := procGetMessage.Call(
uintptr(unsafe.Pointer(msg)),
uintptr(hwnd),
uintptr(msgFilterMin),
uintptr(msgFilterMax))
return int(ret)
}
func TranslateMessage(msg *MSG) bool {
ret, _, _ := procTranslateMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret != 0
}
func DispatchMessage(msg *MSG) uintptr {
ret, _, _ := procDispatchMessage.Call(
uintptr(unsafe.Pointer(msg)))
return ret
}
func LowLevelKeyboardProc (nCode int, wParam WPARAM, lParam LPARAM) LRESULT {
ret, _, _ := procLowLevelKeyboard.Call(
uintptr(nCode),
uintptr(wParam),
uintptr(lParam),
)
return LRESULT(ret)
}
func Start() {
// defer user32.Release()
keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL,
(HOOKPROC)(func(nCode int, wparam WPARAM, lparam LPARAM) LRESULT {
if nCode == 0 && wparam == WM_KEYDOWN {
fmt.Println("key pressed:")
kbdstruct := (*KBDLLHOOKSTRUCT)(unsafe.Pointer(lparam))
code := byte(kbdstruct.VkCode)
fmt.Sprintf("%q", code)
}
return CallNextHookEx(keyboardHook, nCode, wparam, lparam)
}), 0, 0)
var msg MSG
for GetMessage(&msg, 0, 0, 0) != 0 {
}
//~ for {
//~
//~ GetMessage(uintptr(unsafe.Pointer(msg)), 0, 0, 0)
//~ TranslateMessage(msg)
//~ DispatchMessage(msg)
//~ // fmt.Println("key pressed:")
//~
//~ }
UnhookWindowsHookEx(keyboardHook)
keyboardHook = 0
}
func main() {
go Start()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment