Windows 10 GetKeyState weirding out? (Windows API)

Akito

Well-Known Member
I am at the end of my wisdom and need some help.

Here are the relevant parts of my code:
Code:
proc isKeyPressed(virtKeyCode: int32, stateCode: SHORT): bool =
  if GetAsyncKeyState(virtKeyCode) and 0x8000 != 0:
    return true
  else:
    return false

template checkKey(virtKeyCode: int32, keyValue: string, stateCode: SHORT): untyped =
  if isKeyPressed(`virtKeyCode`, `stateCode`): return `keyValue`

proc getCurrentKey(): string {.thread.} =
  for virtKeyCode in 0x01..0xFE.int32:
    case virtKeyCode:
      # of 0x4E: checkKey(virtKeyCode, "n", -32768)
      # of 0x30: result = "none1"
      # of 0x31: result = "none2"
      # of 0x32: result = "none3"
      # of 0x33: result = "none4"
      # of 0x34: result = "none5"
      # of 0x35: result = "none6"
      # of 0x36: result = "none7"
      # of 0x37: result = "none8"
      # of 0x38: result = "none9"
      # of 0x39: result = "none10"
      # of 0x3A..0x40: result = " none11 "
      of 0x41: checkKey(virtKeyCode, "a", -32767.SHORT)
      of 0x42: checkKey(virtKeyCode, "b", -32767.SHORT)
      of 0x43: checkKey(virtKeyCode, "c", -32767.SHORT)
      of 0x44: checkKey(virtKeyCode, "d", -32767.SHORT)
      of 0x45: checkKey(virtKeyCode, "e", -32767.SHORT)
      of 0x46: checkKey(virtKeyCode, "f", -32767.SHORT)
      of 0x47: checkKey(virtKeyCode, "g", -32767.SHORT)
      of 0x48: checkKey(virtKeyCode, "h", -32767.SHORT)
      of 0x49: checkKey(virtKeyCode, "i", -32767.SHORT)
      of 0x4A: checkKey(virtKeyCode, "j", -32767.SHORT)
      of 0x4B: checkKey(virtKeyCode, "k", -32767.SHORT)
      of 0x4C: checkKey(virtKeyCode, "l", -32767.SHORT)
      of 0x4D: checkKey(virtKeyCode, "m", -32767.SHORT)
      of 0x4E: checkKey(virtKeyCode, "n", -32767.SHORT)
      of 0x4F: checkKey(virtKeyCode, "o", -32767.SHORT)
      of 0x50: checkKey(virtKeyCode, "p", -32767.SHORT)
      of 0x51: checkKey(virtKeyCode, "q", -32767.SHORT)
      of 0x52: checkKey(virtKeyCode, "r", -32767.SHORT)
      of 0x53: checkKey(virtKeyCode, "s", -32767.SHORT)
      of 0x54: checkKey(virtKeyCode, "t", -32767.SHORT)
      of 0x55: checkKey(virtKeyCode, "u", -32767.SHORT)
      of 0x56: checkKey(virtKeyCode, "v", -32767.SHORT)
      of 0x57: checkKey(virtKeyCode, "w", -32767.SHORT)
      of 0x58: checkKey(virtKeyCode, "x", -32767.SHORT)
      of 0x59: checkKey(virtKeyCode, "y", -32767.SHORT)
      of 0x5A: checkKey(virtKeyCode, "z", -32767.SHORT)
      else: discard
      
      
const
  hInstance: HINSTANCE = 0
  hookProc: HOOKPROC = lowLeveLKeyboardProc
  msg: LPMSG = nil
  wMsgFilterMin: UINT = 0
  wMsgFilterMax: UINT = 0

let
  hook: HHOOK = SetWindowsHookEx(WH_KEYBOARD_LL, hookProc, hInstance, 0)

proc lowLeveLKeyboardProc(code: int32, wParam: WPARAM, lParam: LPARAM): LRESULT {.stdcall.} =
  if code < 0:
    return nextHook()
  elif code == HC_ACTION:
    stdout.write(getCurrentKey())
  return nextHook()

when isMainModule:
  var hWnd: HWND
  echo "Greetings!"
  let typing = GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax)
  while typing == TRUE:
    TranslateMessage(msg)
    DispatchMessage(msg)

Luckily Nim is an expressive and beautiful language, so I'm sure I do not need to explain much of this code, if you are familiar with the Windows API.

Now, the summary of the current situation:
  • Every key state is recorded and captured correctly.
  • Everything you see works, as it should, i.e. when you press any key (except one) between a-z, the key you press will be printed on the console.
  • All keys (a-z) work PERFECTLY, except the N key with the Virtual Key Code 0x4E.
  • The N key is printed onto the console only, if you press it 3 times in a row. However, that is rather random. Sometimes it works instantly, most of the time you have to spam the N key to get a result printed onto the console.
  • I have tried different keyboards. Same result.
  • I have restarted the computer, etc. Same result.
  • No other general key manipulating programs are installed.
  • As you can see above, every other key is printed in the same way the N key is printed, so the program logic has to be correct, or else all keys would weird out like that. However, even though the program logic stays exactly the same for the N key, this is the only key that is not captured correctly, when using GetKeyState/GetAsyncKeyState.
  • I want to explicitly emphasize, that all keys print the result to the console as expected, except the N key. The program logic is therefore correct.
  • The N key sometimes is printed, if you spam the key a lot. So the logic to retrieve if the N key is pressed or not, must therefore be also correct.

I want to know why the N key is weirding out and how I can fix it.
Please do not question the program logic, as I clearly explained why the program logic has to be correct, except you can refute my explanation.
 

Neemobeer

Application and Cloud Security Engineer
Staff member
Without really being familiar with Nim (but quite a few other language) the code looks fine. Does n type correctly outside of the program? My thought process would point to a hardware issue. I would also try running your code in safe mode to rule out some weird software conflict.
 

Akito

Well-Known Member
The weirdest thing is, that the key gets registered properly, just as the others. When I just plainly echoed the current key state, when pressing any key, then the `n` was correctly registered and shown as pressed and unpressed. However, when I try to `echo` "n" whenever `n` is pressed, I get the issue described above.

For now, I have changed and improved the code in different ways (e.g. I do not print the plain string to console anymore), which makes it work, overall. However, the original issue is still not fixed and perhaps will remain a mystery.

P.S.: I have sent the compiled program to a friend who has a different computer than me. Same issue.
 

Neemobeer

Application and Cloud Security Engineer
Staff member
The only thing that comes to mine is n escaped is a newline char, but you would think the issue would be consistent.
 
Top