2020年总结MFC窗口销毁过程_第1页
2020年总结MFC窗口销毁过程_第2页
2020年总结MFC窗口销毁过程_第3页
2020年总结MFC窗口销毁过程_第4页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、总结 MFC窗口销毁过程假设自己通过 new创建了一个窗口对象pWnd,然后pWnd->Create。则销毁窗口的调用次序:1. 手工调用 pWnd->DestroyWindow();2. DestroyWindow会发送 WM_DESTROY;3. WM_DESTROY 对应的消息处理函数是 OnDestroy() ;4. DestroyWindow会发送 WM_NCDESTROY;5. WM_NCDESTROY对应的消息处理函数是 OnNcDestroy;6. OnNcDestroy最后会调用 PostNcDestroy ;7. PostNcDestroy经常被用户重载以提供释

2、放内存操作。例如可以使用 delete this;通过这种方式,窗口对象对应的窗口和窗口对象本身都被释放了。如果含有子窗口:如果含有子窗口,则调用父窗口的 DestroyWindow 时,它会向子窗口发送 WM_DESTROY和WM_NCDESTROY消息。具体调用顺序参考下文的例子。DestroyWindow对 delete 的影响:应该说前者对后者并没有什么影响。但经常在DestroyWindow间接导致执行的PostNcDestroy 中 delete 窗口对象指针,即deletethis 。CView:PostNcDestroy中唯一的操作就是delete this;CframeWnd

3、:PostNcDestory 也是如此。而默认的CWnd:PostNcDestroy 是空操作, CDialog 中也没有对其进行重载,即也是空。delete对 Destroy 的影响:delete会导致析构函数。 CWnd的析构函数中有对DestroyWindow 的调用,但必须保证:m_hWnd != NULL &&this != (CWnd*) & wndTop && this != (CWnd*)&wndBottom &&this != (CWnd*)&wndTopMost && this !=(C

4、Wnd*)&wndNoTopMost。Cdialog 的析构函数中也有对 DestroyWindow 的调用,但条件比较松,只需要 m_hWnd != NULL。另外 Cdialog:DoModal 也会调用DestroyWindow。CFrameWnd 的 OnClose 中会调用 DestroyWindow,但其析构中不会调用 DestroyWindow。CView的析构也不会调用DestroyWindow。一个 SDI 程序的销毁过程有 CMainFrame类、 CMyView类。并且 CMyView有两个子窗口CMyDlg和 CmyWnd的实例。点击退出按钮, CMainFra

5、me会收到 WM_CLOSE消息。 CframeWnd( CMainFrame的父类)间接会调用 CWnd:DestroyWindow;它首先向CMyView发送 WM_DESTORY和WM_NCDESTROY消息,并引发相应的处理函数;然后向 CMyDlg发送 WM_DESTORY和WM_NCDESTROY消息,并引发相应的处理函数;然后向 CMyWnd发送 WM_DESTORY和WM_NCDESTROY消息,并引发相应的处理函数。具体的执行顺序是:1. 调用 CMainFrame:DestroyWindow2. CFrameWnd:OnDestroy3. CMyView:OnDestroy

6、4. CmyWnd:OnDestroy5. CmyDlg:OnDestroy6. CmyWnd:PostNcDestroy7. CmyWnd的析构8. CmyDlg:OnDestroy9. CmyDlg 的析构10. CMyView:PostNcDestroy11. CmyView 的析构12. CMainFrame 的析构13. CMainFrame:DestroyWindow退出上面情况是假设我们在 CmyWnd和 CmyDlg的 PostNcDestroy 中添加了 delete this 。如果没有添加,则 7,10 不会执行。因为 CView:PostNcDestroy 会执行 CM

7、yView的析构操作。因为用了 delete this ,所以最后执行中调用了 delete this,所以然后CframeWnd:PostNcDestroy 中调CMainFrame的析构操作。如果自己的 CmyDlg和 CmyWnd在 PostNcDestroy 中有 delete this ;则二者会被析构。否则内存泄漏。当然 delete 也可以放在CMyView的析构中做,只是不够 OO。总结可以有两种方法销毁窗口对象对应的窗口和释放窗口对象指针。一种是通过 DestroyWindow。这是比较好的方法,因为最后 MFC会自动相应 WM_CLOSE导致 CframWnd:Destro

8、yWindow 被调用,然后会一次释放所有子窗口的句柄。 用户需要做的是在 PostNcDestroy 中释放堆窗口对象指针。但因为某些对象是在栈中申请的, 所以 delete this 可能出错。这就要保证写程序时自己创建的窗口尽量使用堆申请。另一种是 delete 。Delete 一个窗口对象指针有的窗口类(如CWnd,Cdialog )会间接调用 DestroyWindow,有的窗口类(如 CView,CframeWn)不会调用 DestroyWindow。所以要小心应对。二者是相互调用的,很繁琐。一段很好的文章:(作者:闻怡洋)一个 MFC窗口对象包括两方面的内容:一是窗口对象封装的窗

9、口,即存放在 m_hWnd成员中的 HWND(窗口句柄),二是窗口对象本身是一个 C+对象。要删除一个 MFC窗口对象,应该先删除窗口对象封装的窗口,然后删除窗口对象本身。删除窗口最直接方法是调用CWnd:DestroyWindow或:DestroyWindow ,前者封装了后者的功能。 前者不仅会调用后者,而且会使成员 m_hWnd保存的 HWND无效 (NULL)。如果 DestroyWindow删除的是一个父窗口或拥有者窗口,则该函数会先自动删除所有的子窗口或被拥有者,然后再删除父窗口或拥有者。在一般情况下,在程序中不必直接调用DestroyWindow 来删除窗口,因为 MFC会自动调

10、用DestroyWindow 来删除窗口。例如,当用户退出应用程序时,会产生WM_CLOSE消息,该消息会导致 MFC自动调用 CWnd:DestroyWindow 来删除主框架窗口,当用户在对话框内按了 OK或 Cancel 按钮时,MFC会自动调用 CWnd:DestroyWindow 来删除对话框及其控件。窗口对象本身的删除则根据对象创建方式的不同,分为两种情况。在 MFC编程中,会使用大量的窗口对象,有些窗口对象以变量的形式嵌入在别的对象内或以局部变量的形式创建在堆栈上,有些则用new操作符创建在堆中。对于一个以变量形式创建的窗口对象,程序员不必关心它的删除问题, 因为该对象的生命期总

11、是有限的,若该对象是某个对象的成员变量, 它会随着父对象的消失而消失, 若该对象是一个局部变量,那么它会在函数返回时被清除。对于一个在堆中动态创建的窗口对象, 其生命期却是任意长的。初学者在学习 C+编程时,对 new操作符的使用往往不太踏实,因为用 new在堆中创建对象,就不能忘记用 delete 删除对象。读者在学习 MFC的例程时,可能会产生这样的疑问, 为什么有些程序用 new创建了一个窗口对象,却未显式的用 delete 来删除它呢?问题的答案就是有些 MFC窗口对象具有自动清除的功能。如前面讲述非模态对话框时所提到的,当调用 CWnd:DestroyWindow 或:Destroy

12、Window 删除一个窗口时,被删除窗口的 PostNcDestroy 成员函数会被调用。 缺省的 PostNcDestroy 什么也不干,但有些 MFC窗口类会覆盖该函数并在新版本的 PostNcDestroy 中调用 delete this 来删除对象,从而具有了自动清除的功能。此类窗口对象通常是用 new操作符创建在堆中的, 但程序员不必操心用 delete 操作符去删除它们,因为一旦调用DestroyWindow 删除窗口,对应的窗口对象也会紧接着被删除。不具有自动清除功能的窗口类如下所示。这些窗口对象通常是以变量的形式创建的,无需自动清除功能。所有标准的 Windows控件类。1.

13、从 CWnd类直接派生出来的子窗口对象 (如用户定制的控件) 。2. 切分窗口类 CSplitterWnd 。3. 缺省的控制条类(包括工具条、状态条和对话条)。4. 模态对话框类。具有自动清除功能的窗口类如下所示,这些窗口对象通常是在堆中创建的。1. 主框架窗口类(直接或间接从 CFrameWnd类派生)。2. 视图类(直接或间接从 CView类派生)。读者在设计自己的派生窗口类时,可根据窗口对象的创建方法来决定是否将窗口类设计成可以自动清除的。例如,对于一个非模态对话框来说,其对象是创建在堆中的,因此应该具有自动清除功能。综上所述,对于 MFC窗口类及其派生类来说,在程序中一般不必显式删除窗口对象。 也就是说,既不必调用 DestroyWindow 来删除窗口对象封装的窗口,也不必显式地用 delete 操作符来删除窗口对象本身。只要保证非自动清除的窗口对象是以变量的形式创建的, 自动清除的窗口对象是在堆中创建的, MFC的运行机制就可以保证窗口对象的 _ 删除。如果需要手工删除窗口对象,则应该先调用相应的函数(如CWnd:DestroyWindow)删除窗口,然后再删除

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论