2

I am working with magnetic card reader.

When plugged into a USB port and opening Notepad, I get the following, correct result:

%B4290071074381429^NAZARKO/C M               ^1302101000002024976000000000002?;4290071074381429=13021010000020204976?

When I use a keyboard hook (written in C#) that calls Windows API functions, I get inconsistent results, for example:

%B42()071074381429^NAZARKO/C M               ^1302101000002024976000000000002?;4290071074381429=13021010000020204976?

As you can see, here the problem is that the first '90' becomes '()' as if SHIFT was pressed when the '9' and '0' keys were hit.

The keyboard hook code is from here (Keyboard.cs): https://nappybar.googlecode.com/svn/Keyboard.cs and it is set up the following way:

            _kbHook = new KeyboardHook();
            _kbHook.KeyIntercepted += KeyboardHook_KeyIntercepted;
            _kbHook.SetParameters(KeyboardHook.Parameters.AllowAltTab);
            _kbHook.SetParameters(KeyboardHook.Parameters.PassAllKeysToNextApp);

As stated above, the results I am getting when using this with a card reader are inconsistent. It seems that the keyboard state from (GetKeyboardState) is not entirely correct. Mainly, it sometimes says that SHIFT is pressed when it shouldn't be and the other way around. http://msdn.microsoft.com/en-us/library/windows/desktop/ms646299(v=vs.85).aspx

Does anyone know why this is happening and why it is working correctly in Notepad? And more importantly, how I can fix/work around it? Thank you.

1 Answers1

4

You are using a low-level keyboard hook, which runs in-thread. Therefore, when you call GetKeyboardState you are getting the state of your own local keyboard, not the state of Notepad's keyboard. If you want to continue along this route, you need to track the shift key states manually. Why not just process normal keyboard messages in your application? Why do you need a global hook? If you process them normally, then shift key processing will have occurred and when you call GetKeyboardState you will see the appropriate key states. Converting raw keyboard activity into typed characters is notoriously difficult. In addition to shift key states, you have to worry about Caps Lock and IMEs.

Raymond Chen
  • 44,448
  • 11
  • 96
  • 135
  • Thanks for your answer. The application is running as a kiosk with multiple applications and we want to detect all key presses (or reader input), hence the hook. Manual detection of SHIFT seemed to fix the issue. – user1579177 Aug 06 '12 at 15:22
  • Lucky for you this is a kiosk where you control the keyboard and can ensure it is US-English. Shift states in other languages are much harder. (Note that even in US-English you need to worry about Caps Lock, Ctrl, Alt, and Num Lock.) – Raymond Chen Aug 06 '12 at 15:25
  • 2
    Just use GetAsyncKeyState. It will properly retrieve the values of the modifier keys (shift, control, alt) reguardless of which window is active. GetKeyboardState fails to retrieve them with threading issues. On the other hand, GetAsyncKeyState gets physical properties of keys, so it will not return the toggle state of Caps, Num, and Scroll. After looping through all keys with GetAsyncKeyState (populating a byte array), call GetKeyState for caps, scroll, and num lock, and check their toggle bit (least significant bit), and overwrite the values in the main array. – Triynko Jun 25 '15 at 05:17