我什么时候应该在位图上调用DeleteObject()

时间:2011-12-14 06:06:18

标签: windows winapi gdi

我正在研究一些传统的Win32 / MFC项目。

我发现了以下(伪代码):

HDC hDC = ::CreateCompatibleDC(hDCWnd);
HANDLE hFileMap = ::CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, dwSize, FileMapName);
HBITMAP hBmp = ::CreateDIBSection(hDCWnd, &zBI, DIB_RGB_COLORS, &pvNull, hFileMap, 0);

::SelectObject(hDC, hBmp);
::DeleteObject(hBmp);
::CloseHandle(hFileMap);

// .. do something with hDC ..

::DeleteDC(hDC);

对我来说这看起来很奇怪。任何人都可以解释一下,在我对DC做某事之前删除位图和/或关闭文件句柄是否正确?

感谢。

2 个答案:

答案 0 :(得分:8)

不,这不对。代码调用SelectObject()以将位图选择到设备上下文中,然后调用DeleteObject()以尝试删除位图,同时仍在设备上下文中选择该位图。在这种情况下,DeleteObject()将失败,因此位图被泄露。

http://msdn.microsoft.com/en-us/library/dd183539(v=vs.85).aspx

“当图形对象(笔或画笔)仍被选中到设备上下文中时,不要删除它。”

修改

嗯,这很有意思。我尝试在设备上下文中选择位图时调用DeleteObject(),它也为我返回1。有趣的是,此时实际上并未删除位图;在“已删除”位图上调用GetObject()成功!但是,只要从设备上下文中选择了删除的位图,就会将其删除;此时调用GetObject()失败。我还通过观察任务管理器中的GDI句柄计数来验证。因此,如果位图当前被选择到设备上下文中,显然DeleteObject()将推迟删除,但我不相信这在任何地方都有记录。

HDC hdc = CreateCompatibleDC(NULL);
if (hdc != NULL) {
    HBITMAP hBitmap = LoadBitmap(hInst, MAKEINTRESOURCE(IDB_SAMPLE));

    BITMAP bm = { 0 };
    int numBytes;

    // this succeeds as expected
    numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);

    HBITMAP hOldBitmap = SelectBitmap(hdc, hBitmap);

    DeleteObject(hBitmap);

    // this succeeds -- NOT expected!
    numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);

    SelectBitmap(hdc, hOldBitmap);

    // this fails as expected
    numBytes = GetObject(hBitmap, sizeof(BITMAP), &bm);

    DeleteDC(hdc);
}

底线是您发布的代码似乎有效,但依赖于未记录的行为。我的偏好是保证安全并消除这种依赖。

答案 1 :(得分:6)

Raymond Chen的The Old New Thing中有一篇相关文章解释了这种行为:

  

GDI人员发现很多人陷入困境并试图摧毁   当对象仍然被选入DC时。没通电话   造成两类问题:有些应用程序只是泄露   资源(因为他们认为他们正在摧毁对象,但是   没有)。其他应用程序检查了返回值并吓坏了   如果他们看到DeleteObject实际上没有删除该对象。

     

为了保持这两种类型的应用程序都满意,GDI有时会这样做   (并不总是)说谎,“当然,我删除了你的物品。”它没有   实际上删除它,因为它仍然被选入DC,但它也   将一根绳子系在手指上,最后是一个物体   取消选择,GDI会说,“哦,等等,我应该删除它   对象,“并执行删除。所以GDI所做的谎言并非如此   这是一个“谎言,因为它是对未来的乐观预测。”

http://blogs.msdn.com/b/oldnewthing/archive/2013/03/06/10399678.aspx