书籍:《Visual C++ 2017从入门到精通》的2.3.8 Win32控件编程
环境:visual studio 2022
内容:【例2.33】字体选择对话框
说明:以下内容大部分来自腾讯元宝。
一、结构体定义与核心成员
LOGFONT 结构体 是 Windows GDI 中定义字体属性的核心数据结构,其完整定义如下:
typedef struct tagLOGFONT {
LONG lfHeight; // 字体高度(逻辑单位)
LONG lfWidth; // 字符平均宽度(逻辑单位)
LONG lfEscapement; // 字符串基线与设备 X 轴的夹角(0.1 度)
LONG lfOrientation; // 单个字符基线与设备 X 轴的夹角(0.1 度)
LONG lfWeight; // 字体粗细(0-1000)
BYTE lfItalic; // 是否斜体
BYTE lfUnderline; // 是否下划线
BYTE lfStrikeOut; // 是否删除线
BYTE lfCharSet; // 字符集(如 ANSI_CHARSET、SYMBOL_CHARSET)
BYTE lfOutPrecision; // 输出精度(如 OUT_DEFAULT_PRECIS)
BYTE lfClipPrecision; // 裁剪精度(如 CLIP_DEFAULT_PRECIS)
BYTE lfQuality; // 输出质量(如 DEFAULT_QUALITY、ANTIALIASED_QUALITY)
BYTE lfPitchAndFamily; // 字体间距和系列(如 FF_SWISS | DEFAULT_PITCH)
WCHAR lfFaceName[LF_FACESIZE]; // 字体名称(最多 31 个字符)
} LOGFONT, *PLOGFONT;
关键成员说明:
-
lfHeight:
- 逻辑单位表示字体高度,正值表示绝对高度,负值表示点数(需结合设备上下文转换)。
- 示例公式:
lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72)
(MM_TEXT 模式)。
-
lfWeight:
- 粗细等级,常用宏定义:
FW_DONTCARE(0), FW_THIN(100), FW_NORMAL(400), FW_BOLD(700), FW_BLACK(900)
- 值越大字体越粗。
- 粗细等级,常用宏定义:
-
lfCharSet:
- 字符集类型,常用值:
ANSI_CHARSET
(多语言支持)SYMBOL_CHARSET
(符号字体)DEFAULT_CHARSET
(系统默认)。
- 字符集类型,常用值:
-
lfQuality:
- 输出质量等级,影响字体渲染效果:
DEFAULT_QUALITY
(默认,可接受近似匹配)ANTIALIASED_QUALITY
(抗锯齿,平滑显示)PROOF_QUALITY
(精确匹配,但可能失真)。
- 输出质量等级,影响字体渲染效果:
-
lfPitchAndFamily:
- 组合字段,定义字体间距和系列:
FF_DONTCARE | DEFAULT_PITCH
(默认间距,不指定系列)FF_SWISS | VARIABLE_PITCH
(等宽字体,可变间距)。
- 组合字段,定义字体间距和系列:
二、高级特性与使用场景
1. 字体映射机制
- GDI 会根据
lfFaceName
、lfHeight
、lfCharSet
等属性匹配系统物理字体,若无完全匹配则选择近似字体。 - 示例:指定
"Arial"
但系统中无此字体时,可能映射为"Arial Unicode MS"
。
2. 旋转与方向控制
- lfEscapement 与 lfOrientation:
- 在
GM_ADVANCED
图形模式下,两者可独立设置,用于精确控制文本方向。 - 示例:
lfEscapement = 300
(30 度旋转)。
- 在
3. 跨设备兼容性
- 逻辑字体(
LOGFONT
)可被任意设备上下文(HDC
)选择,确保屏幕与打印机显示一致性。
4. 实际编程应用
- MFC 示例:动态设置字体为宋体并启用抗锯齿:
(参考网页2)LOGFONT lf; gettextstyle(&lf); // 获取当前字体 _tcscpy_s(lf.lfFaceName, _T("宋体")); // 设置字体名称 lf.lfQuality = ANTIALIASED_QUALITY; // 抗锯齿 CFont font; font.CreateFontIndirect(&lf); // 创建字体对象
三、注意事项与常见问题
-
字符集兼容性:
- 使用
SYMBOL_CHARSET
时需注意符号字体可能不支持所有字符。 - 东亚语言建议显式指定
GB2312_CHARSET
或UTF8_CHARSET
。
- 使用
-
性能优化:
- 避免频繁创建相同属性的
LOGFONT
实例,建议重用结构体。
- 避免频繁创建相同属性的
-
错误处理:
- 检查
CreateFontIndirect
返回值是否为NULL
,并通过GetLastError()
定位错误。
- 检查
四、与其他字体相关结构的对比
结构 | 用途 | 动态性 |
---|---|---|
LOGFONT | 定义字体属性,支持复杂配置 | 高 |
FONTINFO | 存储字体度量信息 | 中 |
TEXTMETRIC | 描述设备字体特性 | 低 |
总结
LOGFONT 结构体 是 Windows GDI 中实现动态字体管理的核心组件,其设计通过结构化参数简化了字体属性配置,并依赖系统字体映射机制实现跨设备兼容性。实际开发中需注意字符集选择、旋转参数设置及资源管理,复杂场景可结合 EnumFontFamiliesEx
实现高级筛选。