为了挂钩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
来捕获一些消息。所以我只是希望有经验的人能够遇到类似情况,然后才能提供帮助。
答案 0 :(得分:2)
来自CallWindowProc
的文档:
“如果通过调用
有意义的特殊内部值GetWindowLong
函数并将nIndex
参数设置为GWL_WNDPROC
或DWL_DLGPROC
来获取此值,则它实际上是窗口的地址或对话框过程,或仅对CallWindowProc
“
您不能调用“特殊内部价值”,除非与CallWindowProc
相同,最简单的方法是拨打CalLWindowProc
...
顺便说一句,看看SetWindowSubclass
,它可能会为你缓解一切。
答案 1 :(得分:2)
关于问题2:
从另一个答案的评论来看,听起来你的子类wndprochook是在一个注入进程的DLL中。如果是这种情况,那么在退出期间,您的DLL可能会被卸载,而窗口仍有待处理的消息。所以Window的类仍然指向你的wndproc,但是代码被卸载了,所以它崩溃了。
最安全的做法是在关闭之前恢复原来的wndproc。例如,当您的子类看到WM_DESTROY或WM_NCDESTROY时,您基本上会颠倒在子窗口时执行的步骤:在使用该消息执行CallWindowProc之前,恢复窗口类中的原始wndproc字段。即使有更多的消息流入该窗口,您的代码也将不再被调用。
答案 2 :(得分: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
结束功能