美好的一天,
我一直在使用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()时,我得到一个指针,表示函数没有成功完成.随后调用GetLastError()并快速检查错误代码会给我一个“访问被拒绝”错误.当然,这是合乎逻辑的,因为我正在尝试从我自己的线程访问另一个的WNDPROC的地址,但我想知道是否有任何方法(当然应该有)来规避这一点.
有什么指针吗? (双关语)
最佳答案 在JNA调用之后不要使用GetLastError(). JNA& JNI可能会调用可能会更改上一个错误的其他API.使用该子句声明SetWindowLong抛出LastErrorException,如下所示:
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);
}