gpt4 book ai didi

java - 关闭捕获全局输入事件的 Hook

转载 作者:搜寻专家 更新时间:2023-11-01 03:44:47 24 4
gpt4 key购买 nike

简介

这里举个例子来说明问题。假设我正在跟踪并向用户显示鼠标全局当前位置和最后单击按钮和位置。这是一张图片:

alt text

为了存档捕获 windows 框上的点击事件,这将被发送到其他程序事件消息队列,我使用 winapi 创建了一个钩子(Hook),即 user32.dll 库。这是在 JDK 沙箱之外,所以我使用 JNA 来调用 native 库。

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

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

例子来源

下面的代码不是我写的,而是来自this Oracle 论坛中的问题并部分修复。

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)) != 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, WPARAM wParam,
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.x, info.pt.y));
break;
case CWMouseHook.WM_MBUTTONDOWN:
globalClickEvent(new GlobalMouseClick('M',
info.pt.x, 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)

通知 native 线程( Hook )您不再需要它。当你这样做时,在你的代码中检查

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

发现您不再需要钩子(Hook)并在 native 端终止它。我建议您首先尝试使用内部事件关闭钩子(Hook),例如

CWMouseHook.WM_MBUTTONDOWN

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

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

关于java - 关闭捕获全局输入事件的 Hook ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4527931/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com