GDI:原始DC位图发生变化,无法恢复
我看到一个问题,我无法重新选择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);
}
- 任何已知的场景中会发生这种情况?
- 任何调试提示在位图数据更改时中断?
注:在代码中,我提到“这个失败”。我删除了返回值的断言,以使代码可读。
编辑:我用来解决它的解决方案是使用CDC:SaveDC和CDC :: RestoreDC,而不是存储指针。内存泄漏消失了,并且每个GDI调用都通过了。但我仍然很好奇为什么原始代码泄漏。据我所知,指向默认位图的指针应该是默认的单色位图,可能是GDI世界中的全局位图
让我们来看看OP的代码。
mpOldBitmap = mCanvasDc.SelectObject(mCanvasBmp);
由于mCanvasBmp是一个的CBitmap对象(未指针的CBitmap),第一种称为HGDIOBJ操作者,然后CDC ::选择对象(HGDIOBJ)它返回HGDIOBJ和不的CBitmap *。这应该会导致转换编译器错误。如果将返回的值转换为CBitmap *也是错误的。
摆脱问题的正确方法是传递一个指针。
mpOldBitmap = mCanvasDc.SelectObject(& mCanvasBmp);
这种情况将被称为CDC ::选择对象(*的CBitmap pBitmap)它返回一个的CBitmap *。
//我希望它很清楚。 :)
对不起,这是我的一个错字,试图简化SO的代码。我已更正说明。我还添加了我找到的解决方案,但我仍然很好奇为什么原版不起作用。 – Ryuu
[mcve]必需。 – IInspectable
我认为你的问题是你不能像这样操作(重新创建)一个实例变量。您需要一个指向CBitmap的指针,即CBitmap * mCanvasBmp并“删除”它,并且每次重新创建它就像mCanvasBmp = new CBitmap。 – VuVirt