3

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);
}
}
Michael Rentmeister
  • 167
  • 1
  • 6
  • 24

1 Answers1

2

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.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I'm not doing it for evil purposes, i just want to consume a few keys while my application is open just so if those keys are hotkeys for another program, it doesn't execute it. And what should I return instead? Sorry I'm not too familiar with how jna works – Michael Rentmeister Dec 17 '11 at 01:10
  • @MichaelRentmeister: You must return an LRESULT type, so consider trying `return new LRESULT(1);` – Hovercraft Full Of Eels Dec 17 '11 at 03:54
  • Ah perfect! One problem with the current setup with the key hook though is that it is constantly looking for key input and not doing any of the other tasks that i want it to do because of the while (!quit) { try { Thread.sleep(10); } catch (Exception e) { e.printStackTrace(); } } What would be a good option to make it run independent of other tasks? – Michael Rentmeister Dec 17 '11 at 04:21
  • @MichaelRentmeister: I don't understand what you're asking. What other tasks is this conflicting with? – Hovercraft Full Of Eels Dec 17 '11 at 04:28
  • Source and problem posted above – Michael Rentmeister Dec 17 '11 at 04:36
  • @Michael: I worry that you're calling `run()` on your KeyHook object, that by doing this you may be calling code on the event thread that should be called in a background thread. Take care that all of your listening and `while (true)` loops are done in background threads. If this doesn't solve your problem, then consider creating a small runnable and compilable program with just a GUI and a keyboard hook, and nothing else, an [sscce](http://sscce.org), and posting it here. – Hovercraft Full Of Eels Dec 17 '11 at 04:53
  • Ah perfect! I put it in a separate thread and it works great! Thanks you much for the help! – Michael Rentmeister Dec 17 '11 at 05:18
  • @Michael: Just be sure that Swing code is called on the event thread, else you'll have code that breaks intermittently and unpredictably. Also, make sure you chain the keyhook unless you're absolutely sure that you want to consume it -- in other words chain it in all cases except where you do an action and want to stop all further hooks from activating. – Hovercraft Full Of Eels Dec 17 '11 at 05:34
  • Well after further testing of the `return new LRESULT(1);` I realized that it consumes all key events, not just the ones i want to listen to – Michael Rentmeister Dec 17 '11 at 06:04
  • @Michael: that's what I was afraid of, and that's one of the reasons why doing this can be dangerous. If you absolutely must consume keys, do so inside each case statement, but default to CallNextHookEx for all other situations. – Hovercraft Full Of Eels Dec 17 '11 at 06:29
  • Ahh don't ask me why I didn't think of that.. Thanks again! – Michael Rentmeister Dec 17 '11 at 07:03
  • Rather than polling a member variable with sleep(10), you might be better off calling Object.wait() on an object, and call Object.notifyAll() on that object when you actually want the thread to terminate. – technomage Dec 21 '11 at 03:04