gpt4 book ai didi

java - 如何使用 JNA 处理 WM_QUERYENDSESSION 消息

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:17:40 27 4
gpt4 key购买 nike

我想用 JNA 在 Java 中捕获 WM_QUERYENDSESSION 消息,以便我可以执行关闭方法,因为 Runtime#addShutdownHook(Thread) 在 Windows [1] 上不起作用。我知道这是可以做到的,因为我已经看到它是用 JNIWrapper 实现的,但我想要一个基于 JNA 的解决方案。

JNIWrapper 解决方案

import java.io.File;
import java.io.RandomAccessFile;

import javax.swing.JFrame;

import com.jniwrapper.win32.Msg;
import com.jniwrapper.win32.ui.WindowMessage;
import com.jniwrapper.win32.ui.WindowMessageListener;
import com.jniwrapper.win32.ui.WindowProc;
import com.jniwrapper.win32.ui.Wnd;

public class ShutdownJNIWrapper {

public static void main(String[] args) {
final JFrame frame = new JFrame("Shutdown Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

Wnd frameHandle = new Wnd(frame);
WindowProc frameWindowProc = new WindowProc(frameHandle);
frameWindowProc.addMessageListener(new WindowMessageListener() {
public boolean canHandle(WindowMessage windowMessage, boolean beforeWindowProc) {
return windowMessage.getMsg() == Msg.WM_QUERYENDSESSION && beforeWindowProc;
}

public int handle(WindowMessage windowMessage) {
doSomething();

return 0;
}

private void doSomething() {
final File file = new File("shutdown-jniwrapper.txt");

try {
RandomAccessFile raf = new RandomAccessFile(file, "rw");
raf.writeUTF("quit");
raf.close();
} catch (Exception e) {
}
}
});
frameWindowProc.substitute();
}
}

我尝试使用 WindowProc 回调和接受它作为参数的 SetWindowLong 方法创建自己的 User32 类,但出现以下异常:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Error looking up function 'SetWindowLong': The specified procedure could not be found.

at com.sun.jna.Function.<init>(Function.java:179)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:344)
at com.sun.jna.NativeLibrary.getFunction(NativeLibrary.java:324)
at com.sun.jna.Library$Handler.invoke(Library.java:203)
at $Proxy0.SetWindowLong(Unknown Source)
at ShutdownJNA.main(ShutdownJNA.java:34)

这是我的 User32 类:

import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;
import com.sun.jna.win32.StdCallLibrary;

public interface MyUser32 extends StdCallLibrary {

public static final int WM_QUERYENDSESSION = 0x11;

public static int GWL_WNDPROC = -4;

interface WindowProc extends StdCallCallback {
LRESULT callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam);
}

int SetWindowLong(HWND hWnd, int nIndex, int dwNewLong);

int SetWindowLong(HWND hWnd, int nIndex, WindowProc dwNewLong);
};

以及试图将所有内容放在一起的类:

import javax.swing.JFrame;
import javax.swing.JPanel;

import com.sun.jna.Native;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.LPARAM;
import com.sun.jna.platform.win32.WinDef.LRESULT;
import com.sun.jna.platform.win32.WinDef.WPARAM;


public class ShutdownJNA extends JPanel {

public static void main(String[] args) {
final JFrame frame = new JFrame("Shutdown Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);

try {
HWND hwnd = new HWND();
hwnd.setPointer(Native.getComponentPointer(frame));

MyUser32.WindowProc proc = new MyUser32.WindowProc() {
public LRESULT callback(HWND wnd, int msg, WPARAM param, LPARAM param2) {
if (msg == MyUser32.WM_QUERYENDSESSION) {}

return new LRESULT(0);
}
};

MyUser32 user32 = (MyUser32)Native.loadLibrary("user32", MyUser32.class); //$NON-NLS-1$
user32.SetWindowLong(hwnd, MyUser32.GWL_WNDPROC, proc);
} catch (Exception e) {
e.printStackTrace();
}
}
}

[1] The shutdown hook isn't executed when the application is launched using javaw.exe

最佳答案

确保您的环境中有 JNA 的 jar 文件。 jna.jar 和 platform.jar 必须都在,否则引用会失败。另一件事是,如果您打算加载它们,您通过 JNA 使用的 dll 文件必须在您的环境中(例如 user32.dll)。

关于java - 如何使用 JNA 处理 WM_QUERYENDSESSION 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4901609/

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