Java – turns off the hook that captures global input events

introduce

This is an illustrative example Consider that I am tracking and displaying the global current position of the mouse and finally clicking the button and positioning it to the user This is a picture:

To archive and capture click events in the windows box, they will be sent to the event message queue of other programs. I use WinAPI, namely user32 DLL library to create a hook This is outside the JDK sandbox, so I use JNA to call the native library

All this was perfect, but it didn't close as I expected

My question is – how do I close the following sample programs correctly?

Sample source

The following code is not completely written by me, but is taken from this problem in Oracle forum and partially fixed

import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JLabel;

import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Platform;
import com.sun.jna.Structure;
import com.sun.jna.platform.win32.BaseTSD.ULONG_PTR;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.platform.win32.WinUser.HHOOK;
import com.sun.jna.platform.win32.WinUser.HOOKPROC;
import com.sun.jna.platform.win32.WinUser.MSG;
import com.sun.jna.platform.win32.WinUser.POINT;

public class MouseExample {
    final JFrame jf;
    final JLabel jl1,jl2;
    final CWMouseHook mh;
    final Ticker jt;

    public class Ticker extends Thread {
        public boolean update = true;

        public void done() {
            update = false;
        }

        public void run() {
            try {
                Point p,l = MouseInfo.getPointerInfo().getLocation();
                int i = 0;
                while (update == true) {
                    try {
                        p = MouseInfo.getPointerInfo().getLocation();
                        if (!p.equals(l)) {
                            l = p;
                            jl1.setText(new GlobalMouseClick(p.x,p.y)
                                    .toString());
                        }

                        Thread.sleep(35);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        return;
                    }
                }
            } catch (Exception e) {
                update = false;
            }
        }
    }

    public MouseExample() throws AWTException,UnsupportedOperationException {
        this.jl1 = new JLabel("{}");
        this.jl2 = new JLabel("{}");
        this.jf = new JFrame();
        this.jt = new Ticker();
        this.jt.start();
        this.mh = new CWMouseHook() {
            @Override
            public void globalClickEvent(GlobalMouseClick m) {
                jl2.setText(m.toString());
            }
        };

        mh.setMouseHook();

        jf.setLayout(new GridLayout(2,2));
        jf.add(new JLabel("Position"));
        jf.add(jl1);
        jf.add(new JLabel("Last click"));
        jf.add(jl2);
        jf.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                mh.dispose();
                jt.done();
                jf.dispose();
            }
        });
        jf.setLocation(new Point(0,0));
        jf.setPreferredSize(new Dimension(200,90));
        jf.pack();
        jf.setVisible(true);
    }

    public static class GlobalMouseClick {
        private char c;
        private int x,y;

        public GlobalMouseClick(char c,int x,int y) {
            super();
            this.c = c;
            this.x = x;
            this.y = y;
        }

        public GlobalMouseClick(int x,int y) {
            super();
            this.x = x;
            this.y = y;
        }

        public char getC() {
            return c;
        }

        public void setC(char c) {
            this.c = c;
        }

        public int getX() {
            return x;
        }

        public void setX(int x) {
            this.x = x;
        }

        public int getY() {
            return y;
        }

        public void setY(int y) {
            this.y = y;
        }

        @Override
        public String toString() {
            return (c != 0 ? c : "") + " [" + x + "," + y + "]";
        }
    }

    public static class CWMouseHook {
        public User32 USER32INST;

        public CWMouseHook() throws UnsupportedOperationException {
            if (!Platform.isWindows()) {
                throw new UnsupportedOperationException(
                        "Not supported on this platform.");
            }
            USER32INST = User32.INSTANCE;
            mouseHook = hookTheMouse();
            Native.setProtected(true);
        }

        private static LowLevelMouseProc mouseHook;
        private HHOOK hhk;
        private boolean isHooked = false;

        public static final int WM_LBUTTONDOWN = 513;
        public static final int WM_LBUTTONUP = 514;
        public static final int WM_RBUTTONDOWN = 516;
        public static final int WM_RBUTTONUP = 517;
        public static final int WM_MBUTTONDOWN = 519;
        public static final int WM_MBUTTONUP = 520;

        public void dispose() {
            unsetMouseHook();
            mousehook_thread = null;
            mouseHook = null;
            hhk = null;
            USER32INST = null;
        }

        public void unsetMouseHook() {
            isHooked = false;
            USER32INST.UnhookWindowsHookEx(hhk);
            System.out.println("Mouse hook is unset.");
        }

        public boolean isIsHooked() {
            return isHooked;
        }

        public void globalClickEvent(GlobalMouseClick m) {
            System.out.println(m);
        }

        private Thread mousehook_thread;

public void setMouseHook() {
    mousehook_thread = new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                if (!isHooked) {
                    hhk = USER32INST.SetWindowsHookEx(14,mouseHook,Kernel32.INSTANCE.GetModuleHandle(null),0);

                    isHooked = true;

                    System.out
                            .println("Mouse hook is set. Click anywhere.");
                    // message dispatch loop (message pump)
                    MSG msg = new MSG();
                    while ((USER32INST.GetMessage(msg,null,0)) != 0) {
                        USER32INST.TranslateMessage(msg);
                        USER32INST.DispatchMessage(msg);
                        if (!isHooked)
                            break;
                    }
                } else
                    System.out
                            .println("The Hook is already installed.");
            } catch (Exception e) {
                System.err.println("Caught exception in MouseHook!");
            }
        }
    });
    mousehook_thread.start();
}
        private interface LowLevelMouseProc extends HOOKPROC {
            LRESULT callback(int nCode,WPARAM wParam,MOUSEHOOKSTRUCT lParam);
        }

        private LowLevelMouseProc hookTheMouse() {
            return new LowLevelMouseProc() {
                @Override
                public LRESULT callback(int nCode,MOUSEHOOKSTRUCT info) {
                    if (nCode >= 0) {
                        switch (wParam.intValue()) {
                        case CWMouseHook.WM_LBUTTONDOWN:
                            globalClickEvent(new GlobalMouseClick('L',info.pt.x,info.pt.y));
                            break;
                        case CWMouseHook.WM_RBUTTONDOWN:
                            globalClickEvent(new GlobalMouseClick('R',info.pt.y));
                            break;
                        case CWMouseHook.WM_MBUTTONDOWN:
                            globalClickEvent(new GlobalMouseClick('M',info.pt.y));
                            break;
                        default:
                            break;
                        }
                    }
                    return USER32INST.CallNextHookEx(hhk,nCode,wParam,info.getPointer());
                }
            };
        }

        public class Point extends Structure {
            public class ByReference extends Point implements
                    Structure.ByReference {
            };

            public NativeLong x;
            public NativeLong y;
        }

        public static class MOUSEHOOKSTRUCT extends Structure {
            public static class ByReference extends MOUSEHOOKSTRUCT implements
                    Structure.ByReference {
            };

            public POINT pt;
            public HWND hwnd;
            public int wHitTestCode;
            public ULONG_PTR dwExtraInfo;
        }
    }

    public static void main(String[] args) {
        EventQueue.invokelater(new Runnable() {
            @Override
            public void run() {
                try {
                    new MouseExample();
                } catch (AWTException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Solution

You should call in your thread

User32. PostQuitMessage(0)

Notifies the native thread (hook) that you no longer need it When you do, check in your code

See that you no longer need the hook and terminate it locally I suggest you try to close the hook with an internal event, such as

Just to see if it works properly

In this article: working example of JNA mouse hook, you can see some code that should be helpful to you Cheers!

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>