You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Windows默认对话框字体并将CListCtrl的CHeaderCtrl设为粗体?

问题:设置CListCtrl表头为系统默认粗体字体时触发断言错误

需求

希望将CListCtrl的CHeaderCtrl(表头)设置为粗体显示,不自定义字体,而是使用当前电脑的系统默认字体,仅将默认字体改为粗体,询问是否可行。

当前错误

运行代码时触发Microsoft Visual C++运行时库断言错误:

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

错误发生在代码行:m_headerFont.CreateFontIndirect(&lf);

断点时LOGFONT参数值

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"

示例代码

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))
    {
        // 如果字体是MS Shell Dlg,使用SystemParametersInfo获取系统字体
        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);
            }
        }
    }
}

解决方案

你的需求完全可行——基于系统默认字体生成粗体版本是合理的实现方式。断言错误的核心原因是LOGFONT结构体的lfPitchAndFamily字段未正确设置,MFC在创建字体时会校验该参数的合法性。

修复步骤:

  1. 保留原字体的PitchAndFamily属性:从默认字体获取LOGFONT时,不要覆盖lfPitchAndFamily,或者在修改后确保该字段不为0。你的代码中当前lfPitchAndFamily是0,这不符合字体创建的要求。
  2. 移除不必要的特殊字体判断:MS Shell Dlg是系统占位字体,直接使用GetLogFont获取的参数即可,无需额外调用SystemParametersInfo获取图标标题字体(这会覆盖原有的PitchAndFamily等关键参数)。

修正后的代码:

BOOL CMFCtestDlg::OnInitDialog()
{
    // 原有初始化代码...
    
    CHeaderCtrl* pHeaderCtrl = m_listCtrl.GetHeaderCtrl();
    if (pHeaderCtrl == nullptr)
        return CDialogEx::OnInitDialog();

    CFont* pDefaultFont = pHeaderCtrl->GetFont();
    LOGFONT lf{};
    if (pDefaultFont != nullptr && pDefaultFont->GetLogFont(&lf))
    {
        // 仅修改字体粗细为粗体,保留其他所有系统默认参数
        lf.lfWeight = FW_BOLD;
        // 确保PitchAndFamily字段有效(如果原获取的值为0,可手动设置为DEFAULT_PITCH | FF_DONTCARE)
        if (lf.lfPitchAndFamily == 0)
        {
            lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
        }

        if (m_headerFont.CreateFontIndirect(&lf))
        {
            pHeaderCtrl->SetFont(&m_headerFont);
        }
    }

    return CDialogEx::OnInitDialog();
}

关键说明:

  • lfPitchAndFamily字段需要指定字体的间距和族类,不能为0。从系统字体获取的LOGFONT通常会自带有效值,但若因特殊情况为0,手动设置DEFAULT_PITCH | FF_DONTCARE即可兼容所有系统。
  • 无需针对MS Shell Dlg做特殊处理,因为GetLogFont会自动解析该占位字体为实际使用的系统字体(比如你的环境中是Segoe UI)。
  • 确保m_headerFont是类成员变量(而非局部变量),否则字体对象会在函数结束后销毁,导致表头显示异常。

内容的提问来源于stack exchange,提问作者Michal Hadraba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:58:12