2012-03-22 73 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); 
     } 
});