3

我发现在 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句柄变量'before'和'after'之后是相等的;g_DC 是主窗口 HDC。

如何删除“h”以使 GDI 对象的数量减少?

4

2 回答 2

1

第一次调用 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() 检索到的对象可以被删除,但不是必须的。

于 2013-08-26T23:24:14.047 回答
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;
}
于 2013-08-27T00:07:07.987 回答