3

この C++/MFC MDI アプリケーションでは、各 MDI クライアント ウィンドウに CDialog に基づくフォームが含まれています。このフォームには、非常に多くのコントロール (数百ものコントロールも含む) を含めることができます。GDI ハンドルが比較的すぐに不足することに気付きました (Windows の制限はプロセスごとに 10000 です)。

主な問題は、ほぼすべてのコントロールに設定したフォントでした。多くの場合、Arial 11 などの複数のコントロールに同じ属性を持つフォントが使用されるため、内部参照カウントを使用してフォントを共有しています。

これは役に立ちましたが、CEdit は他のコントロールとは異なる動作をします。同じ共有フォント ハンドルを複数の CEdit に渡す場合、GDI ハンドルの数は CEdit ごとに 1 ずつ増加します。

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 は共有 CFont インスタンスであり、CDialog メンバーとして宣言されています。

同じフォント インスタンスが SetFont に渡されても、反復ごとに dwCount がインクリメントされます。CEdit がフォントのシャドウ コピーを作成するかのように。

pEdit->SetFont(NULL) でさえ、gdi ハンドルの数を増やします!

CStatic などの他のコントロール タイプでは、すべて問題ありません。

これは comctl32.dll のバージョンにも関連しており、バージョン 6.0 を使用すると動作が再現されます。

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")

行を省略すると、comctl32.dll 5.8 が使用され、ハンドルの数は増加しません。

この問題を回避する機会はありますか?

4

0 に答える 0