zoukankan      html  css  js  c++  java
  • 关于SelectObject之后是否要恢复之前的GDI对象

    以下列代码为例

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

  • 相关阅读:
    代理 XP”组件已作为此服务器安全配置的一部分被关闭。系统管理员可以使用 sp_configure 来启用“代理 XP”。
    sql 操作常用操作语句 新增、修改字段等
    easyui 日期控件清空值
    jQuery文件上传插件jQuery Upload File 有上传进度条
    js中文乱码怎么解决【转】
    [转]SqlSever2005 一千万条以上记录分页数据库优化经验总结【索引优化 + 代码优化】一周搞定
    SqlBulkCopy批量添加数据
    常用正则表达式
    查询每张表的大小
    Jquery里的特定小技巧
  • 原文地址:https://www.cnblogs.com/shanql/p/6576444.html
Copyright © 2011-2022 走看看