2012-03-22 9 views
0

バックグラウンドとJFrameにキーボードリスナーがあるシンプルなアプリケーションを作成しようとしています。実際に、私は、リスナーを作成するには、次のコードを使用します。JNA:キーリスナー+ 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の後。問題は、GetMessageのためにJFrameを作成する方法がわからないことです。現在、GetMessageは現在のスレッドをブロックし、そのあとでJFrameを作成することはできません。一方、リスナーは動作しないため、新しいスレッドに入れることはできません。私はあなたが問題を理解することを願っ:)どのようにそれを解決するためのアイデア?

ありがとうございます!

+0

別スレッドを使用できない理由はありませんが、実際にはこれを実行する必要があると感じています。スイングコードを通知できるキーフックにリスナーを配置します。 –

+0

GetMessageを新しいスレッドの中に入れた場合、フックは機能しません。 – peter

答えて

1

[OK]を、これは問題を解決するために何をすべきかです:

私たちは、このフラグメントを捨てる:

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); 
     } 
});