问题描述:
最近正在做一个MFC框架窗口(CFramwWnd)程序,该窗体程序是以对话框项目为框架,在此基础上创建框架窗口(CFramwWnd),框架窗口(CFramwWnd)中没有CDocument及CView,其中增加了分隔条CSplitterWnd类成员,在框架窗口销毁函数中,做了分离m_wndSpltter.Detach();然后在C:Program Files (x86)Microsoft Visual Studio2017EnterpriseVCToolsMSVC14.16.27023atlmfcsrcmfcwincore.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,程序正常运行。