[转] 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之后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函数的意义就行了。
延伸理解下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的关系
位图:DeleteObject;
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
我给你说三种情况,但我们首先做一个假设,就是MFC封装的GDI类在析构时没有做任何动作,也就是说,它是个纯粹的“简单封装”,那么:
1.pBmp->Detach将使C++的对象与GDI对象分离开来,但二者都没有释放。此时必须分别用deletepBmp和DeleteObject将二者分别释放;
2.pBmp->DeleteObject将使GDI对象被释放,而C++对象本身不会释放。你可以用Attach重新使其与某个GDI对象关联,或者,用delete将其释放;
3.delete pBmp(注意,我们假定析构时不调用DeleteObject)将使C++对象消亡,而对应的GDI对象依然存在。要使GDI对象释放,必须再次调用DeleteObject。
注意上面说的第三种情况,在实际的MFC实现中,为了简化程序员的负担,在C++对象析构时,与之关联的GDI对象也会释放。我之所以这样假定,是为了让你明白C++对象与GDI对象的区别。
还有,new的东西不是在栈里,而是在堆里。
[转] Attach、Detach和DeleteObject的更多相关文章
- Attach、Detach和DeleteObject
原文:Attach.Detach和DeleteObject,想飞的梦想 1.CWnd Attatch和Detach的关系 首先,要明白Windows对象和MFC对象的区别. MFC对象实际上并没有把整 ...
- 揭秘 Kubernetes attach/detach controller 逻辑漏洞致使 pod 启动失败
前言 本文主要通过深入学习k8s attach/detach controller源码,了解现网案例发现的attach/detach controller bug发生的原委,并给出解决方案. 看完本文 ...
- Entity Framework 数据部分更新之Attach &&Detach
我们经常会遇到这样的问题:Update一个entity的部分数据时,通常需要new一个新的对象,然后事这新的对象Attach到Context中,代码如下所示: /// <summary> ...
- laravel 多对多关联 attach detach sync
用户表和角色表,多对多关联,一个用户有多个角色,一个角色属于多个用户 添加多对多关联 attach: 给1号用户添加1号角色,并把关联表的column字段赋值为$value,后边的数组需要的时候再添加 ...
- Eloquent Attach/Detach/Sync Fires Any Event
eloquent-attach-detach-sync-fires-any-event I have a laravel project, and I need to make some calcul ...
- CBitmap Detach和DeleteObject的关系
注意:当使用完资源后,必须通过调用函数以释放加速器表.位图.光标.图标以及菜单所占的内存资源: 加速器表:DesteoyAcceleratorTable: 位图:DeleteObj ...
- MFC Attach()函数和Detach()函数
一.Windows对象和MFC对象的区别?MFC对象实际上并没有把整个Windows对象都包装在其中.对于窗口:MFC对象它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口对象 ...
- Attach()和Detach()函数
一.Windows对象和MFC对象的区别? MFC对象实际上并没有把整个Windows对象都包装在其中.对于窗口:MFC对象它只是有一个窗口句柄而已,这个窗口句柄如果指向一个实际存在的窗口对象(窗口对 ...
- 转载JQuery 中empty, remove 和 detach的区别
转载 http://www.cnblogs.com/lisongy/p/4109420.html .empty() 描述: 从DOM中移除集合中匹配元素的所有子节点. 这个方法不接受任何参数. 这个 ...
随机推荐
- 机器学习基石的泛化理论及VC维部分整理(第五讲)
第五讲 Training versus Testing 一.问题的提出 \(P_{\mathcal{D}}\left [ BAD \mathcal{D} \right ] \leq 2M \cd ...
- centos startx 进入桌面后使用中文输入法
(从runlevel 3进入桌面:英文 ,结果用不了中文输入法 囧) 但在中文桌面下可以输入中文 步骤: 由startx可以进入桌面 查看:which startx => /usr/bin/st ...
- 无锁算法CAS 概述
无锁算法CAS 概述 JDK5.0以后的版本都引入了高级并发特性,大多数的特性在java.util.concurrent包中,是专门用于多线并发编程的,充分利用了现代多处理器和多核心系统的功能以编写大 ...
- bzoj 1318: [Spoj744] Longest Permutation 智商题
1318: [Spoj744] Longest Permutation Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 361 Solved: 215 ...
- Delphi逆向
Delphi反汇编内部字符串处理函数/过程不完全列表 名称 参数 返回值 作用 等价形式 / 备注 _PStrCat EAX :目标字符串 EDX :源字符串 EAX 连接两个 Pascal 字符串 ...
- Fiddler 日志
Fiddler 日志(Logging) 在开发扩展插件及编写FiddlerScript时对调试程序非常有用. 1.输出日志 在FiddlerScript脚本中,你可以这样输出输出日志: Fiddler ...
- POJ 1061 青蛙的约会(扩展欧几里德)
点我看题目 题意 : 中文题不详述. 思路 : 设经过s步后两青蛙相遇,则必满足(x+m*s)-(y+n*s) = K*L(k = 0,1,2....) 变形得:(n-m)*s+K*L = x-y ; ...
- POJ3207+tarjan+2-sat
/* 2-sat 题意:给定一个圆,圆上一些点.两点一线.现给出一些线,这些线可以在圆内连起来,也可以在圆外. 问有没有可能所有的线画完 且 不出现相交. 思路:把线画在圆内或圆外 看成一个组合.其它 ...
- 【无聊放个模板系列】BZOJ 3172 (AC自动机)
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #inc ...
- PHP基础语法2
数组 PHP有两种数组:索引数组.关联数组. 函数 自定义函数 自定义函数通过将一组代码封装起来,使代码进行复用,程序结构与逻辑更加清晰 返回值 使用return关键字可以使函数返回值,可以返回包括数 ...