1

为了挂钩 a wndproc,我编写了 awndprochook并使用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以捕获一些消息。所以我只是希望以前遇到过类似情况的经验丰富的人可以提供帮助。

4

3 回答 3

2

从以下文档CallWindowProc

“如果这个值是通过调用参数设置为or的GetWindowLong函数获得的,它实际上要么是一个窗口或对话框过程的地址,要么是一个只对 有意义的特殊内部值nIndexGWL_WNDPROCDWL_DLGPROCCallWindowProc

你不能调用“特殊的内部值”,除非做同样的事情CallWindowProc,最简单的方法是调用CalLWindowProc......

顺便说一句,看看SetWindowSubclass,它可能会为你减轻一些事情。

于 2013-03-22T14:07:02.543 回答
2

关于问题2:

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

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

于 2013-03-22T17:38:21.383 回答
0

谢谢阿德里安·麦卡锡。

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

结束功能

于 2013-08-27T07:25:35.437 回答