2012-03-22 126 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。問題是我不知道如何創建JFrame,因爲GetMessage。現在,GetMessage會阻止當前線程,因此我無法在其後創建JFrame。另一方面,我不能把它放在一個新的線程中,因爲那樣的話,這個監聽器不起作用。我希望你明白這個問題:)任何想法如何解決它?

在此先感謝!

+0

我不明白爲什麼你不能使用單獨的線程,實際上覺得這是你必須要做的。你會把一個監聽器放到可以通知你的swing代碼的關鍵鉤子上。 – 2012-03-22 11:43:44

+0

如果我把GetMessage放入一個新線程中,掛鉤不起作用。 – peter 2012-03-22 11:47:18

回答

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