GDI:原始 DC 位图更改,无法还原



我看到一个问题,即我无法重新选择 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. 位图数据更改时会中断任何调试技巧?

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


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

让我们看看 OP 的代码。

mpOldBitmap = mCanvasDc.SelectObject(mCanvasBmp);

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

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

mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp);

这种情况将称为CDC::SelectObject(CBitmap* pBitmap(,它返回一个CBitmap*

我希望它很清楚。 :)

最新更新