Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ CallWindowProc在退出时崩溃_C++_Winapi - Fatal编程技术网

C++ CallWindowProc在退出时崩溃

C++ CallWindowProc在退出时崩溃,c++,winapi,C++,Winapi,为了钩住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); return CallW

为了钩住
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);
return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);
它失败了,但感谢上帝,我发现
CallWindowProc

return wndproc(hwnd, uMsg, wParam, lParam);
return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);
现在它开始工作了。所以问题1:为什么我们必须使用
CallWindowProc
?简单调用
wndproc
时缺少什么?

钩子运行良好,但当我退出程序时,它崩溃了。当然,所有的事情都已经完成了,这次事故实际上并没有影响到任何事情。但看到撞车还是很糟糕。 因此问题2:这里可能发生了什么以及如何解决它?


很抱歉,我没有关于原始程序如何自行关闭的信息,因为我所做的只是挂接
wndproc
以捕获一些消息。因此,我只希望有足够经验的人能够提供帮助,他们以前遇到过类似的情况。

来自
CallWindowProc
的文档:

return wndproc(hwnd, uMsg, wParam, lParam);
return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);
“如果此值是通过调用
GetWindowLong
函数获得的,并且
nIndex
参数设置为
GWL\u WNDPROC
DWL\u DLGPROC
,则它实际上是窗口或对话框过程的地址,或者一个仅对
CallWindowProc
有意义的特殊内部值。”

您不能调用“特殊内部值”,除非执行与
CallWindowProc
相同的操作,最简单的方法是调用
CallWindowProc


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

来自
CallWindowProc
的文档:

return wndproc(hwnd, uMsg, wParam, lParam);
return CallWindowProc(wndproc, hwnd, uMsg, wParam, lParam);
“如果此值是通过调用
GetWindowLong
函数获得的,并且
nIndex
参数设置为
GWL\u WNDPROC
DWL\u DLGPROC
,则它实际上是窗口或对话框过程的地址,或者一个仅对
CallWindowProc
有意义的特殊内部值。”

您不能调用“特殊内部值”,除非执行与
CallWindowProc
相同的操作,最简单的方法是调用
CallWindowProc

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

关于问题2:

从对另一个答案的评论中,听起来您的子类wndprochook位于注入到进程中的DLL中。如果是这种情况,那么在退出期间,您的DLL可能会被卸载,而窗口仍有消息等待处理。因此窗口的类仍然指向wndproc,但该代码被卸载,因此它会崩溃

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

关于问题2:

从对另一个答案的评论中,听起来您的子类wndprochook位于注入到进程中的DLL中。如果是这种情况,那么在退出期间,您的DLL可能会被卸载,而窗口仍有消息等待处理。因此窗口的类仍然指向wndproc,但该代码被卸载,因此它会崩溃


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

谢谢阿德里安·麦卡锡

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

结束功能

感谢阿德里安·麦卡锡

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

结束函数

wow!这真的解释了…你能给出问题2的一些答案吗?问题2:尝试通过调试器运行它,看看它在哪里中断。在最坏的情况下,将所有内容都放在Try/catch中。@fritzone好吧,问题是我无法通过调试器运行目标程序…我所做的只是在它开始时插入一个dll。wow!t问题2:试着通过调试器运行它,看看它在哪里坏了。在最坏的情况下,把所有的东西都放在一个Try/catch中。@fritzone好吧,问题是我不能通过调试器运行目标程序…我所做的就是在它开始时注入一个dll。我不确定。看到了吗ms表示dll是在目标exe模块之后卸载的。此外,windows肯定应该在实例之前卸载。我说的对吗?但我认为你的回答仍然是值得的,虽然有时可能会分离dll,并且应该尽可能保持所有内容的干净。我不确定。似乎dll是在后面卸载的呃目标exe模块。另外,windows肯定应该在实例之前卸载。我说的对吗?但是我认为你的答案仍然是值得的,也许有时候dll可以分离,应该尽可能保持一切干净。