GDI:原始DC位图发生了变化,无法恢复

时间:2017-08-08 05:23:13

标签: winapi memory-leaks mfc gdi

我发现无法在DC上重新选择原始位图的问题,导致内存泄漏。指向原始位图的指针在整个程序中保持不变,但数据(来自CBitmap :: GetBitmap)从单色变为其他。我不知道位图实际上何时发生变化,但是系统中的某些东西正在引起它。

CBitmap* cMyClass::mpOldBitmap;
CDC cMyClass::mCanvasDc;
CBitmap cMyClass::mCanvasBmp;

void cMyClass::Init()
{
    // One-time initialization
    CDC* pDc = GetDC();
    mCanvasDc.CreateCompatibleDC(pDc);
    mCanvasBmp.CreateCompatibleBitmap(pDc, 10, 10);
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp);
    ReleaseDC(pDc);

    BITMAP bitmap;
    mpOldBitmap->GetBitmap(&bitmap); // A monochrome bitmap, as expected.
}

void cMyClass::Recreate(int newW, int newH)
{
    // 1. Delete existing bitmap:
    if (mpOldBitmap)
    {
        BITMAP bitmap;
        mpOldBitmap->GetBitmap(&bitmap); // This is no longer the monochrome bitmap. It is 8bpp, with random size.

        CBitmap* pCurrBmp = mCanvasDc.SelectObject(mpOldBitmap); // This fails (NULL). I can't de-select my bitmap.
        mCanvasBmp.DeleteObject(); // This fails too, causing memory leak. Actually, it fails in CE6, but not in Win32. Regardless, both platforms will have a memory leak.
    }

    // 2. Recreate the bitmap with new size:
    {
        CDC* pDc = GetDC();
        mCanvasBmp.CreateCompatibleBitmap(pDc, newW, newH);
        ReleaseDC(pDc);
    }

    // 3. Finalize
    mpOldBitmap = mCanvasDc.SelectObject(&mCanvasBmp);
}
  1. 任何可能发生这种情况的已知场景?
  2. 当位图数据发生变化时,是否有任何调试提示?
  3. 注意:在代码中,我提到"这失败"。我删除了返回值上的断言以使代码可读。

    编辑:我用来修复它的解决方案是使用CDC:SaveDC和CDC :: RestoreDC而不是存储指针。内存泄漏消失了,每个GDI调用都通过了。但我仍然好奇为什么原始代码泄露了。据我所知,指向默认位图的指针应该是一个默认的单色位图,可能是GDI世界中的全局位图

1 个答案:

答案 0 :(得分:-1)

让我们看看OP的代码。

mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp);

因为mCanvasBmp是CBitmap对象(不是指向CBitmap的指针),所以首先称为HGDIOBJ运算符,然后是 CDC :: SelectObject(HGDIOBJ),它返回 HGDIOBJ 和不是 CBitmap * 。这应该给出转换编译器错误。如果将返回的值转换为CBitmap *也是错误的。

摆脱问题的正确方法是传递指针。

sizeof(T)

此案例将被称为 CDC :: SelectObject(CBitmap * pBitmap),它返回 CBitmap *

//我希望它非常清楚。 :)