In our C++/MFC MDI application, each MDI client window contains a form based on CDialog that can contain very many controls, even hundreds of them. We have noticed that we run out of GDI handles relatively quickly (windows limit is 10000 per process).
The primary problem was the fonts we set on almost every control. Often a font with the same attributes is used for multiple controls, for example Arial 11, so we share the fonts now, with an internal reference count.
This has helped, however the CEdit behave differently than other controls. When passing the same shared font handle to multiple CEdits, the number of GDI handles still grows by 1 per CEdit.
BOOL CGDIHandlesTestDlg::OnInitDialog()
{
__super::OnInitDialog();
m_font.CreatePointFont(-50, _T("Arial"));
int x = 0, y = 0;
for (int i = 0; i < 100; i++)
{
CRect rc(CPoint(x, y), CSize(10, 10));
CEdit* pEdit = new CEdit();
if (!pEdit->Create(WS_CHILD|WS_BORDER|WS_VISIBLE, rc, this, 1000+i))
break;
pEdit->SetFont(&m_font); // CREATES A NEW GDI OBJECT!!!
DWORD dwCount = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
TRACE(_T("%d\n"), dwCount); // dwCount is incremented on each iteration
x += 10;
}
return TRUE
}
m_font is a shared CFont instance and declared as CDialog member.
On each iteration, dwCount gets incremented even though the same font instance is passed to SetFont. As if CEdit creates a shadow copy of the font.
Even pEdit->SetFont(NULL) increments the number of gdi handles!
With other control types, e.g. CStatic, everything is fine.
It is also related to the version of comctl32.dll, the behavior is reproducible when using version 6.0:
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
If you omit the line, comctl32.dll 5.8 is used, and the number of handles does not grow.
Do we have a chance to work around the problem?