JNA: прослушиватель ключей + JFrame

Я пытаюсь написать простое приложение, в котором у меня есть прослушиватель клавиатуры в фоновом режиме и JFrame. На практике я использую следующий код для создания слушателя:

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 WinUser.WM_KEYUP:
                    case WinUser.WM_KEYDOWN:
                    case WinUser.WM_SYSKEYUP:
                    case WinUser.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(WinUser.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
        System.out.println("Keyboard hook installed, type anywhere, 'q' to quit");
        new Thread() {
            public void run() {
                while (!quit) {
                    try { Thread.sleep(10); } catch(Exception e) { }
                }
                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);
    }
}

Мое требование состоит в том, чтобы создать прослушиватель первым и после него JFrame. Проблема в том, что я не знаю, как создать JFrame из-за GetMessage. Теперь GetMessage блокирует текущий поток, поэтому я не могу создать JFrame после него. С другой стороны, я не могу поместить его в новый поток, потому что тогда слушатель не работает. Надеюсь, вы понимаете проблему :) Есть идеи, как ее решить?

Заранее спасибо!


person peter    schedule 22.03.2012    source источник
comment
Я не вижу причин, по которым вы не можете использовать отдельный поток, и на самом деле чувствую, что это то, что вы должны сделать. Вы бы поместили слушателя в ключевой хук, который мог бы уведомить ваш код свинга.   -  person Hovercraft Full Of Eels    schedule 22.03.2012
comment
Если я помещу GetMessage в новый поток, хук не сработает.   -  person peter    schedule 22.03.2012


Ответы (1)


Хорошо, вот что нужно сделать, чтобы решить проблему:

Выбрасываем этот фрагмент:

new Thread() {
   public void run() {
      while (!quit) {
         try { Thread.sleep(10); } catch(Exception e) { }
      }
      System.err.println("unhook and exit");
      lib.UnhookWindowsHookEx(hhk);
      System.exit(0);
   }
}.start();

а затем мы заключаем код из основного метода в:

new Thread(new Runnable() {
...
}).start();

Затем мы можем ввести, например. :

startListening(); // key listener

JFrame frame = new JFrame();
...
SwingUtilities.invokeLater(new Runnable() {

   @Override
      public void run() {
         frame.setVisible(true);
      }
});
person peter    schedule 23.03.2012