因为要做一个项目,其中一个需求是动态新建一个单文档框架窗口和视图窗口。大致清楚单文档窗口的构建需要新的框架类调用LoadFrame函数来触发。新建并显示窗口并不是大问题,在程序退出时释放框架窗口的相关内存的释放出现了一些问题。
代码实现过程大致是这样的:
首先在应用程序类里定义一个框架类指针:
COpenglFrame *m_pOpenglFrame;// COpenglFrame继承自CFrameWnd类
新建框架窗口的相关代码:
CNewFrameApp* pApp = ( CNewFrameApp* )AfxGetApp(); pApp->m_pOpenglFrame = new COpenglFrame; CCreateContext Context; Context.m_pNewViewClass = RUNTIME_CLASS(COpenglView); pApp->m_pOpenglFrame->LoadFrame(IDR_MENU1,WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE,NULL,&Context); pApp->m_pOpenglFrame->ShowWindow(SW_SHOW);
最后在应用程序类的ExitInstance()函数对框架窗口进行销毁:
int CNewFrameApp::ExitInstance() { // TODO: 在此添加专用代码和/或调用基类 HWND hWnd = NULL; if (NULL!=m_pOpenglFrame) { hWnd = m_pOpenglFrame->GetSafeHwnd(); if (NULL!=hWnd) { m_pOpenglFrame->DestroyWindow(); } } return CWinApp::ExitInstance(); }
编译通过,开始运行。先运行主框架,然后新建一个框架窗口,然后关闭新建的框架窗口,再退出主程序就出现下面的错误:
经过发现,错误是在CNewFrameApp::ExitInstance()函数的m_pOpenglFrame->DestroyWindow()这一句触发的。
我分析,在关闭新建的框架窗口后新建的框架窗口的窗口句柄已经无效,但是其值并非为NULL,使用NULL!=hWnd来判断窗口句柄是否有效并不准确,我要做的是找到一种准确判断窗口句柄是否有效的办法。于是我把代码改为:
int CNewFrameApp::ExitInstance() { // TODO: 在此添加专用代码和/或调用基类 HWND hWnd = NULL; if (NULL!=m_pOpenglFrame) { hWnd = m_pOpenglFrame->GetSafeHwnd(); if(IsWindow(hWnd)) { m_pOpenglFrame->DestroyWindow(); } } return CWinApp::ExitInstance(); }
测试后问题解决,程序可以顺利退出也没有内存泄露。值得一提的是单击新建框架窗口的关闭按钮这时框窗口的相关内存的释放是由它的父类CFrameWnd的PostNcDestroy函数完成:
void CFrameWnd::PostNcDestroy() { // default for frame windows is to allocate them on the heap // the default post-cleanup is to 'delete this'. // never explicitly call 'delete' on a CFrameWnd, use DestroyWindow instead delete this; }