0

I have implemented keyBoardHook, but however cannot detect the character pressed while shift key is down.

I have tried using the GetAsyncKeyState function of windows to detect when shift key is pressed. But this does not process shift+2 = @. it overrides the shift key and prints the keycode for 2.

i can obtain every key but however Shift + 2 are detected both as separate keys (Even though [SHIFT+2] gives @ on my keyboard). IE: The program outputs both SHIFT, and 2, but not what they produce: @.

Question:

How can i detect the characters produced when shift key is down.

Code i have written so far.

public class Keyhook {
private static volatile boolean quit;
private static HHOOK hhk;
private static LowLevelKeyboardProc keyboardHook;

public static void main(String[] args) {
    final User32 lib = User32.INSTANCE;
    HMODULE hMod = Kernel32.INSTANCE.GetModuleHandle(null);
    keyboardHook = new LowLevelKeyboardProc() {
        public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
            if (nCode >= 0) {
                switch (wParam.intValue()) {
                    case User32.WM_KEYUP:

                    break;
                    case User32.WM_KEYDOWN: 
                    if(lib.GetAsyncKeyState(160) == 1){
                         System.out.println(info.vkCode);    
                      }
                    break;
                    case User32.WM_SYSKEYUP:

                        break;
                    case User32.WM_SYSKEYDOWN:
                        System.err.println("in callback, key=" + info.vkCode);
                        if (info.vkCode == 81) {
                            quit = true;
                        }
                }
            }
            return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
        }
    };
    hhk = lib.SetWindowsHookEx(User32.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
    System.out.println("Keyboard hook installed, type anywhere, 'q' to quit");
    //noinspection ConstantConditions
    new Thread() {
        public void run() {
            while (!quit) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            System.err.println("unhook and exit");
            lib.UnhookWindowsHookEx(hhk);
            System.exit(0);
        }
    }.start();

    // This bit never returns from GetMessage
    int result;
    MSG msg = new MSG();
    while ((result = lib.GetMessage(msg, null, 0, 0)) != 0) {
        if (result == -1) {
            System.err.println("error in get message");
            break;
        } else {
            System.err.println("got message");
            lib.TranslateMessage(msg);
            lib.DispatchMessage(msg);
        }
    }
    lib.UnhookWindowsHookEx(hhk);
}
}
paktrick
  • 93
  • 2
  • 8
  • Have a look to this answer http://stackoverflow.com/q/6237250/233906 and it's solution http://melloware.com/products/jintellitype/index.html – Cerber Oct 06 '11 at 10:22

2 Answers2

0

According to the LowLevelKeyboardProc documentation, the reason you cannot detect the shift key:

Note When this callback function is called in response to a change in the state of a key, the callback function is called before the asynchronous state of the key is updated. Consequently, the asynchronous state of the key cannot be determined by calling GetAsyncKeyState from within the callback function.

gangelo
  • 3,034
  • 4
  • 29
  • 43
0

There's no easy way to predict the generated output (some key combinations don't produce any output). If Java generates a KeyTyped event, the generated string will be provided in the event, but I don't think there's any API (Java or native) that provides you with a keystroke to key string mapping.

technomage
  • 9,861
  • 2
  • 26
  • 40