我发现在FillRgn()Windows GDI API函数之后,此函数中使用的GDI对象以某种方式“卡在”内部系统映射中的某处并且不会正确删除:在对象上调用DeleteObject()成功返回,但进程的GDI对象数量不会减少。这是代码:
void gditest()
{
HBRUSH h = CreateSolidBrush(RGB(255, 237, 5));
HRGN rgn = CreateRectRgn(0, 100, 100, 0);
FillRgn(g_DC, rgn, h);
int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
SelectObject(g_DC, GetStockObject(WHITE_BRUSH));
int rs = DeleteObject( h );
if ( !rs )
throw;
int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
}
代码演示了删除HBRUSH后的句柄变量'之前'和'之后'相等; g_DC是HDC的主窗口。
如何删除'h'以便GDI对象的数量减少?
答案 0 :(得分:2)
第一次调用SelectObject()时,必须记住返回值,并在完成DC后再次选择它。此外,您必须删除所有创建的GDI对象。
void gditest()
{
HBRUSH h = CreateSolidBrush(RGB(255, 237, 5));
HRGN rgn = CreateRectRgn(0, 100, 100, 0);
FillRgn(g_DC, rgn, h);
int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
HBRUSH oldBrush = SelectObject(g_DC, GetStockObject(WHITE_BRUSH));
SelectObject( g_DC, oldBrush );
int rs = DeleteObject( h );
if ( !rs )
throw;
DeleteObject( rgn );
int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
}
注意:
可以删除GetStockObject()检索的对象,但它们不必删除。
答案 1 :(得分:0)
GDI正在缓存画笔和区域资源,或者它是一个错误。删除画笔或区域后,计数不会下降。在Windows 7上测试过。这是我快速又脏的重复代码:
#include <cassert>
#include <iostream>
#include <windows.h>
void PrintGdiCount() {
std::cout << ::GetGuiResources(::GetCurrentProcess(), GR_GDIOBJECTS)
<< std::endl;
}
int main() {
PrintGdiCount();
::GdiSetBatchLimit(1); // disable batching
HDC hdcScreen = ::GetDC(NULL);
PrintGdiCount();
HDC hdcMemory = ::CreateCompatibleDC(hdcScreen);
PrintGdiCount();
HBITMAP hbmpMemory = ::CreateCompatibleBitmap(hdcScreen, 100, 100);
PrintGdiCount();
HBITMAP hbmpOld = reinterpret_cast<HBITMAP>(::SelectObject(hdcMemory, hbmpMemory));
PrintGdiCount();
HBRUSH hbrush = ::CreateSolidBrush(RGB(255, 127, 32));
PrintGdiCount();
HRGN hrgn = ::CreateRectRgn(0, 0, 50, 50);
PrintGdiCount();
// ::FillRgn(hdcMemory, hrgn, hbrush); // doesn't affect GDI count
PrintGdiCount();
BOOL bDeletedBrush = ::DeleteObject(hbrush);
assert(bDeletedBrush);
PrintGdiCount(); // expected decrement, but it doesn't
::DeleteObject(hrgn);
PrintGdiCount(); // expected decrement, but it doesn't
::SelectObject(hdcMemory, hbmpOld);
::DeleteObject(hbmpMemory);
PrintGdiCount();
::DeleteDC(hdcMemory);
PrintGdiCount();
::ReleaseDC(NULL, hdcScreen);
PrintGdiCount(); // result is 2 higher than initial count
return 0;
}