原文:Attach、Detach和DeleteObject 想飞的梦想

1.CWnd Attatch和Detach的关系

首先,要明白Windows对象和MFC对象的区别。

  MFC对象实际上并没有把整个Windows对象都包装在其中,它只是有一个窗口句柄而已,这个窗口 句柄如果指向一个实际存在的窗口对象(窗口对象,也就是WNDCLASS,是一个Windows对象),那么这个MFC对象就是有效的,否则这个MFC对 象是空的。如果你还不明白,请回忆一下,当我们使用MFC创建一个窗口时,是分两步进行的,第一步,new一个CWnd对象,这一步是创建MFC对象,但 是其中的HWND还是非法的,因为对应的Windows对象还没有被创建出来;第二步,调用CWnd的成员函数Create创建真正的Windows对 象,同时,把先前创建的MFC的CWnd对象的HWND成员指向该窗口,这样才算创建完毕一个窗口。而如果你是用SDK方式,那么只要创建一个 WNDCLASS结构,然后调用Create或者CreateEx就创建了一个窗口。

好,现在回答你的问题。你可以假设,现在你已经有了一个有效窗口句柄,那么你想把这个窗口和一个CWnd对象关联起来怎么办?很简单,用Attach,其实就是让一个CWnd对象的HWND成员指向这个窗口句柄。这就是Attach主要完成的任务。
      第二个,关于Detach。如前所述,WNDCLASS其实和CWnd根本没有什么关系。它们之间只是通过CWnd的成员HWND联系起来的。如果把 Attach看做“联姻”的话,那么Detach就是“离婚”了,通俗地说,就是切断一个CWnd对象和一个有效窗口的脐带。为什么要切断呢?因为 CWnd是C++的对象,C++的对象有一个生存期的概念,脱离了该对象的作用域,这个对象就要被销毁,但是Windows对象没有这个特点,当销毁 CWnd对象的时候,我们不一定希望WNDCLASS一起被销毁,那么在此之前,我们就先要把这个“脐带”剪断,以免“城门失火,殃及池鱼”。
      Detach之后CMenu就释放了HMENU的控制权,析构的时候就不会销毁菜单句柄。

CWnd,CDC, Cxxx等都是MFC的类,这些类提供了很多成员函数来执行系统调用等操作,但是核心的类成员数据都是句柄,(包括窗口句柄,DC句柄,线程句柄等)。
      m_hWnd,m_hDC,m_hThread如果这些类对象的这些句柄为空,就表示无效对象。比如你 CWnd * pWnd = new CWnd,执行是合法的,但是没有Create就没有窗口句柄,基本上就是一个无效对象,只是系统内存申请了内存分配空间而已,很多操作都无法执行 (debug模式下会出现断言错误窗口)。
      但是,假如你申请了一个CWnd,CDC的对象实体,可以使用Attach来指定一个有效的句柄付给这个对象。那么此对象就是Valid的了。你可能跟踪看看Attach的实现,其实就是给m_hxxx赋值,而Detach就是值复位。
      这2个操作没有申请内存释放内存操作,就是一个赋值而已,是不是成对使用看你代码的实际情况吧。只要理解了这2函数的意义就行了

其实CWnd,CDC等类就是多了一个包装,方便用户(程序开发者)使用,如果用SDK开发,完全可以实现一样的功能。

句柄是操作系统内核对象,而窗口指针、DC指针是用户对象(由你的程序管理)。

延伸理解下Attach/Detach:
      Attach是把一个C++对象与一个WINDOWS对象关联,直到用detach则把关联去掉。如果Attach了以后没有Detach,则C++对象 销毁的时候WINDOWS对象跟着一起完蛋。Attach了以后,C++对象的指针WINDOWS对象的HWND会有一个映射关系,其作用相当于你直接用 一个C++对象去Create一个WINDOWS对象,例如   CEdit   edit;   edit.create(...) 并且此映射是永久的,知道此对象完蛋为止。如果用类似GetDlgItem函数也可以返回一个指针,并可以强制转换。GetDlgItem会到映射表里 找。有2种映射表,一中是永久的,一种是临时的。直接用C++对象创建的WINDOWS对象或者是通过Attach的对象的映射关系都被放到永久表中,否 则就在临时表中创建映射。所以GetDlgItem不推荐你保存返回的指针,因为你很难保证你的WINDOWS对象跟C++对象的关联是否放在永久表中。 如果映射是放在临时表中,那么在空闲时间会被自动删除。用Attcah完全是为了方便用MFC类的成员函数去操纵WINDOWS对象。

2.CBitmap Detach和DeleteObject的关系

注意:当使用完资源后,必须通过调用函数以释放加速器表、位图、光标、图标以及菜单所占的内存资源;

加速器表:DesteoyAcceleratorTable;
位图:DeleteObject;光标:DestroyCursor;
图标:Destroylcon;菜单:DestroyMenu

 

HBITMAP/CBitmap/BITMAP 三者之间的关系转换:

HBITMAP hBitmap;
CBitmap bitmap;
BITMAP bm;
bitmap.Attach(hBitmap);//由HBITMAP 得到关联的CBitmap
bitmap.GetBitmap(&bm); // 由CBitmap 得到关联的BITMAP
hBitmap=(HBITMAP)bitmap.GetSafeHandle();//由CBitmap得到相关的HBITMAP   

  一些通过FromHandle()或者Create...()获得的指针需要delete吗?    
  我知道很多gdi对象在Create后需要使用DeleteObject()释放其句柄,但是否需要delete呢?
我给你说三种情况,但我们首先做一个假设,就是MFC封装的GDI类在析构时没有做任何动作,也就是说,它是个纯粹的“简单封装”,那么:
1.pBmp->Detach将使C++的对象与GDI对象分离开来,但二者都没有释放。此时必须分别用deletepBmp和DeleteObject将二者分别释放;
2.pBmp->DeleteObject将使GDI对象被释放,而C++对象本身不会释放。你可以用Attach重新使其与某个GDI对象关联,或者,用delete将其释放;
3.deletepBmp(注意,我们假定析构时不调用DeleteObject)将使C++对象消亡,而对应的GDI对象依然存在。要使GDI对象释放,必须再次调用DeleteObject。
注意上面说的第三种情况,在实际的MFC实现中,为了简化程序员的负担,在C++对象析构时,与之关联的GDI对象也会释放。我之所以这样假定,是为了让你明白C++对象与GDI对象的区别。
还有,new的东西不是在栈里,而是在堆里。

没有整理与归纳的知识,一文不值!高度概括与梳理的知识,才是自己真正的知识与技能。 永远不要让自己的自由、好奇、充满创造力的想法被现实的框架所束缚,让创造力自由成长吧! 多花时间,关心他(她)人,正如别人所关心你的。理想的腾飞与实现,没有别人的支持与帮助,是万万不能的。
本文转自wenglabs博客园博客,原文链接:http://www.cnblogs.com/arxive/p/5929295.html,如需转载请自行联系原作者

[转] Attach、Detach和DeleteObject相关推荐

  1. Attach、Detach和DeleteObject

    原文:Attach.Detach和DeleteObject ,想飞的梦想 1.CWnd Attatch和Detach的关系 首先,要明白Windows对象和MFC对象的区别. MFC对象实际上并没有把 ...

  2. Entity Framework 数据部分更新之Attach Detach

    我们经常会遇到这样的问题:Update一个entity的部分数据时,通常需要new一个新的对象,然后事这新的对象Attach到Context中,代码如下所示: 1 /// <summary> ...

  3. CBitmap Detach和DeleteObject的关系

    注意:当使用完资源后,必须通过调用函数以释放加速器表.位图.光标.图标以及菜单所占的内存资源:       加速器表:DesteoyAcceleratorTable:       位图:DeleteO ...

  4. Attach()和Detach()函数

    一.Windows对象和MFC对象的区别? MFC对象实际上并没有把整个Windows对象都包装在其中. 对于窗口:MFC对象它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口 ...

  5. MFC Attach()函数和Detach()函数

    一.Windows对象和MFC对象的区别? MFC对象实际上并没有把整个Windows对象都包装在其中. 对于窗口:MFC对象它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口 ...

  6. CBitmap Detach DeleteObject关系

    CBitmap Detach DeleteObject关系        http://blog.sina.com.cn/s/blog_4b3c1f950100ggdx.html 注意:当使用完资源后 ...

  7. Jquery empty() remove() detach() 方法的区别

    方法简介: empty() This method removes not only child (and other descendant) elements, but also any text ...

  8. 绘图:BITMAP和DIB区别

    1,BITMAP 即位图. (位图位图,位上的图.图的信息以位保存)TMAP由四部分构成:位图文件头,位图信息头,调色板,和位图信息. 关于它们的详细信息及作用可参考相关资料,位图创建时,以从下至上的 ...

  9. windows无法配置此无线连接_Kubernetes 1.18功能详解:OIDC发现、Windows节点支持,还有哪些新特性值得期待?...

    Kubernetes 1.18发布,一些对社区产生影响的新特性日渐完善,如 KSA(Kubernetes Service Account) tokens的OIDC发现和对Windows节点的支持.在A ...

最新文章

  1. WIN7、XP局域网共享问题和重置IP协议
  2. 中文TTS文字转语音合成模块合成成品带喇叭 替代SYN6288和XFS5152
  3. if not exist Oracle,oracle 兑现 if not exist 方法
  4. python读什么英文-Python常用英文单词有哪些?
  5. Leetcode 102. Binary Tree Level Order Traversal(二叉树的层序遍历)
  6. iphone屏幕镜像连电视_手机股票行情:在电视上投射或镜像安卓手机屏幕的三个简单步骤...
  7. 微信终端自研 C++协程框架的设计与实现
  8. osx+配置+php扩展,Mac系统升级到10.9(mavericks)时安装php扩展问题解决
  9. linux 编译环境包,linux上war包编译环境搭建
  10. 那些年,我们解析过的前端异常
  11. Yahoo! Screwdriver:可扩展的持续集成工具
  12. 实验楼Python项目
  13. 单引号、双引号和不加引号区别
  14. SparkSQL架构
  15. 基于HMM的语音识别技术原理
  16. python字符串出栈方法_Python学习之路_day_04(字符串与列表的内置方法)
  17. 结构体初始化、结构体指针、结构体数组
  18. Dart语言之旅(完全翻译版)
  19. IT民工也在老龄化?
  20. 51nod3155 跳房子

热门文章

  1. JavaScript中的appendChild()方法
  2. 【Python】用Python制作一个名片管理系统
  3. 孩子,我想当富豪的妈妈---一位犹太妈妈的金钱观
  4. el-dialog el-tabs结合样式改造
  5. 密码学数学基础——群、环、域
  6. 性能测试之cpu监控的结论
  7. 【Web前端】配色方案(全览)
  8. HashMap 如何解决 hash 冲突
  9. MySQL数据库中插入图片
  10. 欧拉定理——数论定理