Search code examples
javaeventsglobaljnakeyhook

Using jna to keyhook and consume


I'm making an auto clicker that uses jna to hook global input from the keyboard and mouse. For the keyboard hook im using http://code.google.com/p/goldriver/source/browse/trunk/king/src/jnacontrib/w32keyhook/KeyHook.java?r=36.

I was wondering if there was any possible way to consume the key event so other applications don't process it?

Fixed with return new LRESULT (1);

Now I'm having a problem with it not continuing with the rest of the code, here is the source. My program keeps listening for keyboard input and doesn't continue to even show the GUI.

public class GUI extends javax.swing.JFrame{

ArrayList<MEvent> events;

public static final int RUNNING = 0;
public static final int PAUSED = 1;
public static final int STOPPED = 2;
public static final int LISTENING = 3;

private int process = STOPPED;
private String display;

private JTable Events;
DefaultTableModel list;
Loader loader;
private static MouseHook mh;
static private KeyHook kh;
static GUI gui;
Robot robot;

/** Creates new form GUI */
public GUI() {
    initComponents();
    loader = new Loader(this);
    events = new ArrayList<MEvent>();
    list = new DefaultTableModel();
    mh = new MouseHook(this,list);
    mh.setMouseHook();

    list.addColumn("Type");
    list.addColumn("X");
    list.addColumn("Y");
    list.addColumn("Sleep");
    try {
        robot = new Robot();
    } catch (AWTException ex) {}


    displayProcess(process);
    Events.setModel(list);
    kh = new KeyHook(this);
    kh.run();
}

public static void main(String args[]) {

    java.awt.EventQueue.invokeLater(new Runnable() {
        public void run() {
            gui = new GUI();
            gui.setVisible(true);
        }
    });


}

}

public class KeyHook implements Runnable{
private static volatile boolean quit;
private static HHOOK hhk;
private static LowLevelKeyboardProc keyboardHook;

private GUI gui;
User32 lib;
HMODULE hMod;
public boolean isHooked = false;

public KeyHook(final GUI gui) {
    this.gui = gui;
    lib = User32.INSTANCE;
    hMod = Kernel32.INSTANCE.GetModuleHandle(null);
    Native.setProtected(true);
}

@Override
public void run() {
    keyboardHook = new LowLevelKeyboardProc() {
        public LRESULT callback(int nCode, WPARAM wParam, KBDLLHOOKSTRUCT info) {
            if (nCode >= 0) {
                switch (wParam.intValue()) {
                    case WinUser.WM_KEYUP:
                        switch(info.vkCode){
                            //F7
                            case 0x76:
                                System.out.println("F7");
                                gui.listen();
                                break;

                            //F8
                            case 0x77:
                                System.out.println("F8");
                                gui.stopListening();
                                break;
                            //F9
                            case 0x78:
                                //System.out.println("F9");
                                //gui.start();
                                break;
                            //F10
                            case 0x79:
                                //gui.pause();
                                break;
                            //F11
                            case 0x7A:
                                //gui.stop();
                                break;
                            //ESC
                            case 0x1B:
                                quit = true;
                                break;
                        }
                        break;
                    case WinUser.WM_KEYDOWN:

                       break;
                    case WinUser.WM_SYSKEYUP:

                        break;
                    case WinUser.WM_SYSKEYDOWN:

                        break;
                }
            }
            return new LRESULT(1);//lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());//
        }
    };
    hhk = lib.SetWindowsHookEx(WinUser.WH_KEYBOARD_LL, keyboardHook, hMod, 0);
    //noinspection ConstantConditions
    new Thread() {
        public void run() {
            while (!quit) {
                try {
                    Thread.sleep(10);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            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);
}
}

Solution

  • Yeah, don't call

    return lib.CallNextHookEx(hhk, nCode, wParam, info.getPointer());
    

    In the call back method, ... but that's kind of an evil thing to do, isn't it? And if not evil, potentially dangerous.