你好,
我一直在使用 JNA 与 Windows API 进行交互,现在我在创建窗口时卡住了。据我所做的如下: 1. 已创建现有窗口的子窗口并获得有效的处理程序。 2. 了解 Windows 中的每个窗口都有一个不间断的消息分发循环。 3. 了解将我的窗口包含在消息分发循环中的最佳方法是使用类似于以下代码的内容(不是我的,但我也会这样做):
final LONG_PTR prevWndProc = new LONG_PTR(User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_WNDPROC)); //this is to obtain a pointer to the WNDPROC of the parent window, which we are going to need later
wndProcCallbackListener = new WndProcCallbackListener()
{
public LRESULT callback(HWND hWnd, int uMsg, WPARAM uParam, LPARAM lParam)
{
if (uMsg == WTSAPI.WM_POWERBROADCAST)
{
System.out.println("WM_POWERBROADCAST Event: hWnd="+hwnd+", uMsg="+uMsg+", uParam="+uParam+", lParam="+lParam);
}
else if (uMsg == WTSAPI.WTS_SESSION_CHANGE)
{
System.out.println("WTS_SESSION_CHANGE Event: hWnd="+hwnd+", uMsg="+uMsg+", uParam="+uParam+", lParam="+lParam);
}
//Call the window's actual WndProc so the events get processed.
return User32.INSTANCE.CallWindowProc(prevWndProc, hWnd, uMsg, uParam, lParam);
}
};
//Set the WndProc function to use our callback listener instead of the window's one.
int result = User32.INSTANCE.SetWindowLong(hwnd, User32.GWL_WNDPROC, wndProcCallbackListener);
但是,我的问题是当我为父窗口(我的第一行代码) 调用 GetWindowLong() 时,我得到的指针为 0,表示函数未成功完成。随后调用 GetLastError() 并快速检查错误代码,我得到了一个“访问被拒绝” 错误。这当然是合乎逻辑的,因为我正在尝试从我自己的线程访问另一个线程的 WNDPROC 地址,但我想知道是否有任何方法(当然应该有)来规避它。
有什么指点吗? (双关语)
最佳答案
不要在 JNA 调用后使用 GetLastError()。 JNA 和 JNI 可能会调用其他可能更改最后一个错误的 API。使用子句 throws LastErrorException 声明 SetWindowLong,如下所示:
int SetWindowLongA(int hWnd, int nIndex, WndProcCallbackListener dwNewLong)
throws LastErrorException;
注意名称后面的“A”。它明确使用 ANSI 版本。您也可以使用 SetWindowLongW。
确保您的回调实现了 Callback 和 StdCall。我更喜欢尽可能多地使用基本类型,因为这使得映射对于 JNA 而言快速且明显:
public interface WndProcCallbackListener extends Callback, StdCall {
int callback(int hWnd, int Msg, int wParam, int lParam);
}
关于windows - 在 JNA 中创建一个 native Windows 窗口,并使用 GWL_WNDPROC 创建一些 GetWindowLong,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4041174/