关于SelectObject之后是否要恢复之前的GDI对象
以下列代码为例
{
// 创建内存DC
CDC mMemDc;
mMemDc.CreateCompatibleDC( &dc );
// 创建兼容位图
CBitmap bmpMemBmp;
bmpMemBmp.CreateCompatibleBitmap( &mMemDc, , );
CBitmap* pOldBmp = mMemDc.SelectObject( &bmpMemBmp );
// 在内存DC上绘图
BOOL bRet = mMemDc.Ellipse( , , , );
// 从内存DC上拷贝至显示DC
dc.BitBlt( , , , , &mMemDc, , , SRCCOPY );
// 恢复
// When you finish with the CBitmap object created with the
// CreateCompatibleBitmap function, first select the bitmap out of the device context, then delete the CBitmap object.
//mMemDc.SelectObject( pOldBmp );
}
以上代码最后被注释的部分,按照MSDN上的说法,要将之前的GDI对象SelectObjec回去,防止CBitmap bmpMemBmp中的GDI对象删除失败。
CBitmap析构函数调用基类的~CGdiObject,~CGdiObject中会调用 ::DeleteObject函数来删除GDI对象,关于API函数::DeleteObject(HGDIOBJ hObject) MSDN上有如下说法,if the specified handle is not valid or is currently selected into a DC, the return value is zero.意思是传入的对象句柄无效或者已经被选进DC中的,会返回0,即删除失败。按照这个说法,上文代码最后那部分代码不应该被注释,否则会导致GDI对象删除失败,从而造成资源泄露。
但是,根据实验结果看,并没有造成资源的泄露,使用Process Explorer软件查看GDI句柄数,并没有一直上涨

将GDI对象选入DC, 在没有SelectObject出来之前调用DeleteObject返回的也是成功的,何解?
我想这些都是属于系统底层的机制,为了安全起见,在没有把握的情况下,还是按照官方给出的文档来做,
SelectObject
The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.
HGDIOBJ SelectObject(
HDC hdc, // handle to DC
HGDIOBJ hgdiobj // handle to object
);
Remarks
This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object.
注:MFC那边的SelectObject,即CDC::SelectObject, 也需要遵循这个规则,查看MFC得知,MFC对这个并没有额外的去处理,^-^
补充:
直接用WIN32缩写,也验证了上面的论点,GDI对象在DC中,DeleteObject能删除成功,
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (message)
{
case WM_CREATE:
return (); case WM_PAINT:
{
hdc = BeginPaint (hwnd, &ps);
TCHAR szStr[] = TEXT("A Window!");
TextOut (hdc, , , szStr, _countof(szStr) ); HPEN hPen = CreatePen( PS_DASH, , RGB(, , ) );
HPEN hOldPen = (HPEN)SelectObject( hdc, (HGDIOBJ)hPen ); Ellipse( hdc, , , , ); // 以下也能删除成功,这个hPen还在dc中
BOOL bRet = DeleteObject( (HGDIOBJ)hPen ); EndPaint (hwnd, &ps);
return ();
}
case WM_DESTROY:
PostQuitMessage ();
return ();
}
return DefWindowProc (hwnd, message, wParam, lParam);
}
结论:为了安全起见,遵循MSDN文档上的约定
关于SelectObject之后是否要恢复之前的GDI对象的更多相关文章
- GDI编程
图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...
- GDI编程小结
图形设备接口(GDI)是一个可运行程序,它接受Windows应用程序的画图请求(表现为GDI函数调用),并将它们传给对应的设备驱动程序,完毕特定于硬件的输出,象打印机输出和屏幕输出.GDI负责Wind ...
- VC++学习之GDI概述
VC++学习之GDI概述 图形设备接口(GDI)是一个可执行程序,它接受Windows应用程序的绘图请求(表现为GDI函数调用),并将它们传给相应的设备驱动程序,完成特定于硬件的输出,象打印机输出和屏 ...
- MFC/Windows API 使用过的函数(持续更新)
/*******************使用默认画笔对象**************************** // //绘制矩形 pDC->MoveTo(50, 50); //返回值是一个指 ...
- 浅谈Windows API编程
WinSDK是编程中的传统难点,个人写的WinAPI程序也不少了,其实之所以难就难在每个调用的API都包含着Windows这个操作系统的潜规则或者是windows内部的运行机制…… WinSDK是编程 ...
- ORACLE恢复数据
ORACLE恢复删除表或表记录 一:表的恢复 对误删的表,只要没有使用PURGE永久删除选项,那么从flash back区恢复回来希望是挺大的.一般步骤有: 1.从flash back里查询 ...
- Oracle DB 执行表空间时间点恢复
• 列出在执行表空间时间点恢复(TSPITR) 时会发生的操作 • 阐释TSPITR 使用的术语的定义 • 确定适合将TSPITR 用作解决方案的情况 • 确定时间点恢复的正确目标时间 • 确定不能使 ...
- iOS开发 - 数据归档与恢复 NSKeyedArchiver
归档与恢复归档 归档,英文Archiver['ɑrkɪvə],这里指的是将OC的对象存储为一个文件或者网络上的一个数据块. 恢复归档.英文UnArchiver,指的是将一个来自文件或网络的归档数据块恢 ...
- 【RMAN】TSPITR--RMAN表空间基于时间点的自动恢复
[RMAN]TSPITR--RMAN表空间基于时间点的自动恢复 一.1 BLOG文档结构图 一.2 前言部分 一.2.1 导读 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其 ...
随机推荐
- 几种支持动作模型格式的比较(MD2,MD5,sea3d) 【转】
最近使用了几种不同的模型格式做人物动作的表现,记录一下优缺点 1) MD2 数据内容: 记录了所有动作顶点数据 数据格式: 二进制 动作文件: 动作文件合并在一个模型文件 文件大小: 动作多时很大 ...
- CentOS6.5_64bit下编译安装MySQL-5.6.23
转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/44785511 ************************************** ...
- CSS3中的动画效果-------Day72
还记得么,在前面也曾实现过"仅仅用css让div动起来",还记得当时是怎么实现的么,是的,transition,针对的也比較局限,仅仅有旋转角度啊,长宽啊之类的,所以说,与其说是动 ...
- DataTable和DataRow利用反射直接转换为Model对象的扩展方法类
DataTable和DataRow利用反射直接转换为Model对象的扩展方法类 /// <summary> /// 类 说 明:给DataTable和DataRow扩展方法,直接转换为 ...
- ZYThumbnailTableView---堪比一个小型阅读App
Demo github地址: https://github.com/liuzhiyi1992/ZYThumbnailTableView 原文地址:http://zyden.vicp.cc/zythum ...
- java ArrayList倒序
用Collections.reverse(list)即可.如:List<String> list = Arrays.asList(new String[] {"aa", ...
- nginx的源代码分析--间接回调机制的使用和类比
nginx使用了间接回调机制.结合upstream机制的使用来说明一下,首先明白几个事实: 1)事实上ngxin和下游client的连接使用的是ngx_http_connection_t,每一个连接相 ...
- Mac OS command line TestNG - “Cannot find class in classpath” error
直接eclipse执行.xml文件可以正确执行 在mac下执行却总报错: [TestNG] [Error] Cannot find class in classpath 最后解决办法,classpat ...
- 一致性Hash简单介绍和使用
背景: 一致性Hash用于分布式缓存系统,将Key值映射到详细机器Ip上,而且添加和删除1台机器的数据移动量较小,对现网影响较小 实现: 1 Hash环:将节点的Hash值映射到一个Hash环中.每一 ...
- Dynamic Language Runtime (DLR) 初深
本文主要包括两个内容:DLR在.Net中的位置和一次DLR的调用过程. 1. DLR在. Net 中的位置 图1 DLR 包括哪些内容? 1. Expression Tree(表达式树). 2. Dy ...