博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于SelectObject之后是否要恢复之前的GDI对象
阅读量:4627 次
发布时间:2019-06-09

本文共 2849 字,大约阅读时间需要 9 分钟。

 

以下列代码为例

{                // 创建内存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 ,          // handle to DC  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文档上的约定

转载于:https://www.cnblogs.com/shanql/p/6576444.html

你可能感兴趣的文章
traefik添加多证书
查看>>
忽略UserInterfaceState.xcuserstate
查看>>
ReactNative--Flexbox布局
查看>>
java实现读取文件大全
查看>>
[Cordova] 无法显示Alert视窗
查看>>
借助过度区选择阈值
查看>>
评论列表显示及排序,个人中心显示
查看>>
JavaScript 实现鼠标拖动元素
查看>>
js 模糊查询 (360接口)
查看>>
python+rabbitMQ实现生产者和消费者模式
查看>>
“模态”对话框和“后退”按钮
查看>>
关于javascript实现的网站页面侧边悬浮框"抖动"问题
查看>>
linux_命令格式和命令提示符
查看>>
Cocos2d-X-3.0之后的版本的环境搭建
查看>>
when case group by 的用法集合
查看>>
洛谷P1908 逆序对
查看>>
转义符
查看>>
poj 1019
查看>>
asp.net mvc上传文件
查看>>
bitmq集群高可用测试
查看>>