c++visual-studiowinapifontsmfc

Is possible to get windows default dialog font (MS Shell Dlg) and change its attributes, e.g. bold?


I want to make header (CHeaderCtrl) of CListCtrl bold. I dont want to develop my own font, because I want to respect system default font, which is on each computer different. I want only make default font bold. Is it possible? Below code throw error:

Microsoft Visual C++ Runtime Library
---------------------------
Debug Assertion Failed!

Program: C:\Windows\SYSTEM32\mfc140ud.dll
File: D:\a\_work\1\s\src\vctools\VC7Libs\Ship\ATLMFC\Src\MFC\wingdi.cpp
Line: 1113

in line: m_headerFont.CreateFontIndirect(&lf); - see picture below. enter image description here

In moment of breakpoint is value of lf:

   lfHeight: -12
   lfWidth: 0
   lfEscapement: 0
   lfOrientation: 0
   lfWeight: 700
   lfItalic: 0 '\0'
   lfUnderline: 0 '\0'
   lfStrikeOut: 0 '\0'
   lfCharSet: 1 '\x1'
   lfOutPrecision: 0 '\0'
   lfClipPrecision: 0 '\0'
   lfQuality: 0 '\0'
   lfPitchAndFamily: 0 '\0'
   lfFaceName: 0x00000004b38fc8cc L"Segoe UI"

Code example:

class CMFCtestDlg : public CDialogEx
{
    CFont m_headerFont;
    //....
    //...
    BOOL OnInitDialog();
}

BOOL CMFCtestDlg::OnInitDialog()
{
    //.......
    //.......
    CFont *pDefaultFont = pHeaderCtrl->GetFont();
    LOGFONT lf{0};
    if(pDefaultFont != nullptr && pDefaultFont->GetLogFont(&lf))
    {
        // If the font is MS Shell Dlg, use SystemParametersInfo to get the system font
        if(_tcscmp(lf.lfFaceName, _T("MS Shell Dlg")) == 0)
        {
            if(SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0))
            {
                lf.lfWeight = FW_BOLD;
                m_headerFont.CreateFontIndirect(&lf);
                pHeaderCtrl->SetFont(&m_headerFont);
            }
        }
    }
}

Solution

  • Well, my comment above was wrong, I thought it was failing because it couldn't create the font with the parameters you had passed. But the reason is that the m_headerFont object already contains a valid font handle at that point. You are reusing the object, but CFont::CreateFontIndirect() calls CGdiObject::Attach(), which "asserts" that the object is "empty" (m_hObject==NULL). Therefore you must use another CFont object or instead clear m_headerFont before the CreateFontIndirect() call:

        .
        .
        DeleteObject(m_headerFont.Detach()); // detach and delete the old HFONT
        m_headerFont.CreateFontIndirectW(&lf);
        .
        .