加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 关闭捕获全局输入事件的钩子

发布时间:2020-12-15 02:22:54 所属栏目:Java 来源:网络整理
导读:介绍 这是一个说明问题的例子.考虑我正在跟踪并显示鼠标全局当前位置和最后点击按钮并定位给用户.这是一张图片: 要在Windows框中存档捕获点击事件,将会发送到其他程序事件消息队列,我使用winapi即user32.dll库创建一个钩子.这是在JDK沙箱之外,所以我使用JNA
介绍

这是一个说明问题的例子.考虑我正在跟踪并显示鼠标全局当前位置和最后点击按钮并定位给用户.这是一张图片:

要在Windows框中存档捕获点击事件,将会发送到其他程序事件消息队列,我使用winapi即user32.dll库创建一个钩子.这是在JDK沙箱之外,所以我使用JNA来调用本机库.

这一切都很完美,但它没有像我期望的那样关闭.

我的问题是 – 如何正确关闭以下示例程序?

示例来源

下面的代码不是由我完全编写的,而是取自Oracle论坛中的this问题并部分修复.

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

解决方法

在你的线程中你应该打电话

User32.PostQuitMessage(0)

通知本机线程(挂钩)您不再需要它.
当你这样做时,在你的代码中检查

while ((USER32INST.GetMessage(msg,
null,0)) != 0)

看到你不再需要钩子并在本机端终止它.我建议你先尝试用一个内部事件关闭钩子,例如

CWMouseHook.WM_MBUTTONDOWN

只是为了看它是否正常工作.

在这篇文章中:Working example of JNA mouse hook你可以看到一些应该对你有帮助的代码.干杯.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读