2017-08-08 131 views
0

我看到一个问题,我无法重新选择DC上的原始位图,导致内存泄漏。指向原始位图的指针在整个程序中保持不变,但数据(来自CBitmap :: GetBitmap)从单色变为其他。我不知道位图实际更改的时间,但系统中的某些内容正在导致它。GDI:原始DC位图发生变化,无法恢复

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. 任何调试提示在位图数据更改时中断?

注:在代码中,我提到“这个失败”。我删除了返回值的断言,以使代码可读。


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

+1

[mcve]必需。 – IInspectable

+0

我认为你的问题是你不能像这样操作(重新创建)一个实例变量。您需要一个指向CBitmap的指针,即CBitmap * mCanvasBmp并“删除”它,并且每次重新创建它就像mCanvasBmp = new CBitmap。 – VuVirt

回答

-1

让我们来看看OP的代码。

mpOldBitmap = mCanvasDc.SelectObject(mCanvasBmp); 

由于mCanvasBmp是一个的CBitmap对象(未指针的CBitmap),第一种称为HGDIOBJ操作者,然后CDC ::选择对象(HGDIOBJ)它返回HGDIOBJ和不的CBitmap *。这应该会导致转换编译器错误。如果将返回的值转换为CBitmap *也是错误的。

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

mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp); 

这种情况将被称为CDC ::选择对象(*的CBitmap pBitmap)它返回一个的CBitmap *

//我希望它很清楚。 :)

+0

对不起,这是我的一个错字,试图简化SO的代码。我已更正说明。我还添加了我找到的解决方案,但我仍然很好奇为什么原版不起作用。 – Ryuu