MFC中销毁Windows对象需要注意的问题

MFC  销毁Windows对象需要注意的问题

<reference : MFC TNO 17>

文档介绍如何使用 CWnd::PostNcDestroy()的使用方法
MFC中用C++对象来封装一个Window对象,这样需要注意一些重要的问题:
销毁一个C++封装的Window对象必须用DestroyWindow而不是delete

 问题:
MFC中Window对象(指从CWnd对象中派生的新对象)同时代表着一个C++对象(在应用程序堆Heap上分配)和一个句柄(windows管理器在系统资源中分配) 所以必须要定义销毁Windows对象的方法约束: 来预防内存泄露和系统资源未回收 抑或 内存和系统资源被多次释放;

 

因为这不仅仅只是内存管理的问题,Windows中的窗体是与界面相关的,所以它同时关联一些的资源,系统资源的管理问题比应用程序的内存管理带来的问题往往会更加严重。

 

销毁Windows对象
有2种可行的方案来销毁一个windows 对象:
1     调用CWnd::DestroyWindow()或Windows API DestroyWindow()
2     显式的调用delete操作符

 

第一种方法迄今为止是最通用的方法,甚至于代码中不直接调用,如在程序中关闭窗体时的
WM_CLOSE消息处理的默认行为,Frame关闭时同时会调用DestroyWindow来销毁所有的子窗体;

 

第二种方法用delete对象来销毁一个Window Object是很少用到,只限于以下提及的几种:
当销毁一个Windows 窗体,最后一个发送给窗体的消息是WM_NCDESTROY 默认的CWnd处理该消息的方法为CWnd::OnNcDestroy() 会将句柄与C++对象分离,然后调用虚函数PostNcDestroy() 一些类会重载这个方法来delete C++对象

 

默认的CWnd::PosNcDestroy()的行为不作出任何方式的处理,这适用于那些在栈(stack)上分配的内存和内嵌(embedded)于其它的C++对象的Windows对象; 但是对于那些在堆上分配的Windows对象这种默认的处理方式则不适用(不包括那些内嵌的对象)

 

这些在堆上分配的Windows对象需要在重载PosNcDestroy()并在其中delete this;这样才可以完全释放关联在C++对象上的内存 尽管默认的window对象在其析构函数中会在m_hwnd不是空值NULL时调用DestroyWindow但是这不会形成循环递归调用 应为在清除时句柄会脱离掉(detach)并被设为空值

 

注意:
一般CWnd::PostNcDestroy会在WM_NCDESTROY消息处理之后调用,但是默认的在构造窗体
Create()函数调用失败以后 仍然会调用CWnd::PostNcDestroy()

 

MFC中需要自动清理的类(Auto Cleanup Classes)
以下为不需要自动清理的MFC类:
1 标准windows控件(CStatic CEdit CListBox etc)
2  所有直接从CWnd中派生的子窗体 (如自定义控件)
3  切分窗体(CSplitterWnd)
4  default control bar
5  对话框
6  全部的标准对话框(如CFileDialog CColorDialgo) 除了CFindReplaceDialog
7  所有由ClassWizard派生的对话框

以下的为需要自动清理的MFC类 它们一般分配在堆上:
1 Main Frame Windows 一般直接从CFrameWnd中派生的类 
2 View windows   直接或间接从CView中派生的类

 
如果在程序设计中需要打破以上的约定,那么就需要在PostNcDestroy中做出相应的处理

最常见莫过于 在堆上分配一个无模式对话框;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CWnd类提供了微软基础类库所有窗口类的基本功能。 CWnd对象Windows的窗口不同,但是两者有紧密联系。CWnd对象是由CWnd的构造函数和析构函数创建或销毁的。另一方面,Windows的窗口是Windows的一种内部数据结构,它是由CWnd的Create成员函数创建的,而由CWnd的虚拟析构函数销毁。DestroyWindow函数销毁Windows的窗口,但是不销毁对象。 CWnd类和消息映射机制隐藏了WndProc函数。接收到的Windows通知消息通过消息映射被自动发送到适当的CWnd OnMessage成员函数。你可以在派生类重载OnMessage成员函数以处理成员的特定消息。 CWnd类同时还使你能够为应用程序创建Windows的子窗口。先从CWnd继承一个类,然后在派生类加入成员变量以保存与你的应用程序有关的数据。在派生类实现消息处理成员函数和消息映射,以指定当消息被发送到窗口时应该如何动作。 你可以经过两个步骤来创建一个子窗口。首先,调用构造函数CWnd以创建一个CWnd对象,然后调用Create成员函数以创建子窗口并将它连接到CWnd对象。 当用户关闭你的子窗口时,应销毁CWnd对象,或者调用DestroyWindow成员函数以清除窗口并销毁它的数据结构。 在微软基础类库,从CWnd派生了许多其它类以提供特定的窗口类型。这些类有许多,包括CFrameWnd,CMDIFrameWnd,CMDIChildWnd,CView和CDialog,被用来进一步派生。从CWnd派生的控件类,如CButton,可以被直接使用,也可以被进一步派生出其它类来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值