关于SelectObject之后是否要恢复之前的GDI对象
2017-03-18 22:17
369 查看
以下列代码为例
以上代码最后被注释的部分,按照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返回的也是成功的,何解?
我想这些都是属于系统底层的机制,为了安全起见,在没有把握的情况下,还是按照官方给出的文档来做,
注:MFC那边的SelectObject,即CDC::SelectObject, 也需要遵循这个规则,查看MFC得知,MFC对这个并没有额外的去处理,^-^
补充:
直接用WIN32缩写,也验证了上面的论点,GDI对象在DC中,DeleteObject能删除成功,
结论:为了安全起见,遵循MSDN文档上的约定
{ // 创建内存DC CDC mMemDc; mMemDc.CreateCompatibleDC( &dc ); // 创建兼容位图 CBitmap bmpMemBmp; bmpMemBmp.CreateCompatibleBitmap( &mMemDc, 100, 100 ); CBitmap* pOldBmp = mMemDc.SelectObject( &bmpMemBmp ); // 在内存DC上绘图 BOOL bRet = mMemDc.Ellipse( 0, 0, 100, 100 ); // 从内存DC上拷贝至显示DC dc.BitBlt( 0, 0, 100, 100, &mMemDc, 0, 0, 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 (0); case WM_PAINT: { hdc = BeginPaint (hwnd, &ps); TCHAR szStr[] = TEXT("A Window!"); TextOut (hdc, 0, 0, szStr, _countof(szStr) ); HPEN hPen = CreatePen( PS_DASH, 10, RGB(255, 0, 0) ); HPEN hOldPen = (HPEN)SelectObject( hdc, (HGDIOBJ)hPen ); Ellipse( hdc, 10, 100, 200, 150 ); // 以下也能删除成功,这个hPen还在dc中 BOOL bRet = DeleteObject( (HGDIOBJ)hPen ); EndPaint (hwnd, &ps); return (0); } case WM_DESTROY: PostQuitMessage (0); return (0); } return DefWindowProc (hwnd, message, wParam, lParam); }
结论:为了安全起见,遵循MSDN文档上的约定
相关文章推荐
- 关于SelectObject之后是否要恢复之前的GDI对象
- [翻译自mos文章]不完全恢复之后,open resetlogs之前,怎么快速的检查数据库是否处于一致性的状态?
- 关于IE控件frameset导致GDI对象泄漏的问题
- 《MFC windows程序设计》中关于GDI对象的选定
- 20140810 关于js中如何判断一个对象{}是否为空
- 关于GDI资源使用后未释放,导致GDI对象猛增,程序花屏,异常退出的问题
- ios-ios 7之前和之后关于状态栏隐藏的介绍
- 请问关于在JAVASCRIPT中判断是否是对象的函数?
- 关于Android的onResume的2点体会(程序切换之后恢复状态)
- 关于转屏禁止onCreate android 3.0版本之前和之后的区别
- 关于Python踩坑,a = "//" 之后 a is "//" 语句是否为True?
- 关于应用程序出现窗口不完整,GDI对象猛增,GDI资源泄漏的问题的探讨
- 关于DateTime对象序列化为Json之后的若干问题
- 关于GetActiveObject,如何判断所取得对象的类型、、、可以用来检测某个程序是否运行
- WebView注入Java对象注意事项,4.2之前版本,4.2之后的区别
- 关于GDI对象泄露查找的经验总结
- 关于数据恢复,记一次修复SD卡 RAW 之后的修复过程
- 关于check-in应该是在代码审查之前还是之后
- 关于直接比较两个对象是否相等或则说List集合里是否包含某个对象的问题