1 Reply Latest reply: Mar 22, 2012 10:03 AM by 925770 RSS

    JNA: key listener + JFrame

    925770
      Hello,
      I'm trying to write a simple application where I have a keyboard listener in the background and JFrame. Practically, I use the following code to create the listener:

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

      My requirement is to create the listener as the first and after it JFrame. The problem is that I don't know how to create JFrame because of GetMessage. Now, GetMessage blocks the current thread so I can't create JFrame after it. On the other hand, I can't put it in a new Thread because then, the listener doesn't work. I hope you understand the issue :) Any ideas how to solve it?

      Thanks in advance!
        • 1. Re: JNA: key listener + JFrame
          925770
          Ok, this is what should be done to solve the problem:

          We throw out this fragment:

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

          and next, we enclose code from the main method in:

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

          Then, we are free to type in the main method e.g. :

          startListening(); // key listener

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

          @Override
          public void run() {
          frame.setVisible(true);
          }
          });