解决MFC中因控件类多次Attch造成的销毁窗口过程中CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); ASSERT(pWnd != NULL); 断言失败的

问题描述:

最近正在做一个MFC框架窗口(CFramwWnd)程序,该窗体程序是以对话框项目为框架,在此基础上创建框架窗口(CFramwWnd),框架窗口(CFramwWnd)中没有CDocument及CView,其中增加了分隔条CSplitterWnd类成员,在框架窗口销毁函数中,做了分离m_wndSpltter.Detach();然后在C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\atlmfc\src\mfc\wincore.cpp文件中的:

1 CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
2 ASSERT(pWnd != NULL);

断言失败的问题。

 

寻找原因:

因为一开始并不知道是因m_wndSpltter.Detach();报错,

参考了:

深入解析Windows窗口创建和消息分发

https://www.cnblogs.com/findumars/p/6329614.html

之后,有了更清晰的认识。因为之前调试时会经常进入MFC源代码,基本的消息泵框架这块还有一定概念的。

先得找到报错的窗口句柄到底是属于哪个控件的。

(注:窗口中的控件都继承于CWnd类)

 

解决方法:

1..F5调试,弹出报错后,点击重试,得到了报错的句柄,在spy++中查询该句柄。

2.打开spy++,查找本程序窗品,可定位到该窗口句柄。

3.可是CSplitterWnd窗口类成员的显示的是:AfxMDIFramw140sud。

4.此时怀疑是CSplitterWnd,再次重复步聚1、2在报错代码处插入断点,在CMyFrame::OnClose()处添加处成员的HWND值。这果也可以编辑断点条件:

(0x00580D40 == hWnd || hWnd == 0x002F1140 || hWnd == 0x00B81060) && nMsg == 0x2

依次是主窗口句柄、CSplitterWnd、句柄、以CSplitterWnd的子窗口句柄,0x2为WM_DESTROY消息。

5.报错后的句柄,对比CSplitterWnd句柄,就是它了。

6.找到始作俑者后,再次调试时,跟进去CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);代码,在LookupPermanent()中返回NULL。很明显m_permanentMap中没了这个句柄。

7.再看Detach()做了什么,RemoveHandle,一切原因找到了,我在OnClose()处,多于的做了一次Detach(),导到在销毁窗口时,寻找该窗口句柄时返回NULL。

8.全部移除其它的Detach,程序正常运行。

 

上一篇:windows消息机制框架原理【简单版本】


下一篇:隐藏 Windows任务栏中的窗口显示