CallWindowProc退出时崩溃

CallWindowProc crash on exit

本文关键字:崩溃 退出 CallWindowProc      更新时间:2023-10-16

为了钩住wndproc,我写了一个wndprochook并使用SetWindowLong:

wndproc=(WNDPROC)GetWindowLong(hwnd_1,GWL_WNDPROC);
SetWindowLong(hwnd_1,GWL_WNDPROC,(LONG)wndprochook);

现在我必须在wndproc中做一些事情,在函数结束时,我调用原始的wndproc:

return wndproc(hwnd, uMsg, wParam, lParam);

它失败了,但感谢上帝我找到了CallWindowProc:

return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);

现在它工作了。问题1:为什么我们必须使用CallWindowProc ?

调用wndproc时缺少什么?

钩子运行良好,但是当我退出程序时,它崩溃了。当然,一切都完成了,崩溃实际上并不影响任何事情。但看到坠机还是很糟糕。问题2:这里可能发生了什么?如何解决?

我很抱歉,我没有关于原始程序如何关闭自己的信息,因为我所做的只是挂钩wndproc来捕获一些消息。所以我只是希望有足够的经验,曾经遇到过类似情况的人可以帮助我。

来自CallWindowProc的文档:

“如果这个值是通过调用GetWindowLong函数获得的,而nIndex参数设置为GWL_WNDPROCDWL_DLGPROC,那么它实际上要么是窗口或对话框过程的地址,要么是一个只对CallWindowProc

有意义的特殊内部值。

不能调用特殊的内部值“除了和CallWindowProc一样,最简单的方法是调用CalLWindowProc & help;

顺便说一下,看看SetWindowSubclass,它可能会让你轻松一些。

关于问题2:

从对另一个答案的评论中,听起来你的子类windprochook是在注入到进程中的DLL中。如果是这种情况,那么在退出期间,您的DLL可能被卸载,而仍然有消息等待窗口。所以Window的类仍然指向你的windproc,但是那个代码被卸载了,所以它崩溃了。

最安全的做法可能是在关闭之前恢复原来的windproc。例如,当你的子类看到WM_DESTROY或WM_NCDESTROY时,你本质上逆转了你在子类化窗口时所做的步骤:在使用该消息执行CallWindowProc之前,在窗口类中恢复原始的windowproc字段。您的代码将不再被调用,即使有更多的消息进入该窗口。

感谢Adrian McCarthy。

Private Function WndProc(ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Select Case MSG
    Case WM_CUT, WM_PASTE, WM_CLEAR
        WndProc= 1
    Case WM_DESTROY, WM_NCDESTROY
        Call UnHookRKey(hWnd)
    Case Else
        WndProc= CallWindowProc(lngPrevWndProc, hWnd, MSG, wParam, lParam)
End Select

结束函数