书籍:《Visual C++ 2017从入门到精通》的3.8.2 字体对话框的使用
环境:visual studio 2022
内容:[例 3.11] 字体对话框的使用
说明:以上内容大部分来自腾讯元宝。
以下是关于 Windows API 中 LOGFONT 结构体的详细解析,涵盖其定义、成员功能、应用场景及注意事项:
一、结构体概述
LOGFONT(Logical Font)是 Windows 系统中用于描述字体属性的核心数据结构,定义在 <wingdi.h>
中。它通过 14 个成员完整定义了字体的外观特征,常用于 CreateFont
/CreateFontIndirect
函数创建字体对象,或通过 GetObject
获取现有字体属性。
typedef struct tagLOGFONT {
LONG lfHeight; // 字体高度
LONG lfWidth; // 字体平均宽度
LONG lfEscapement; // 行文本倾斜角度
LONG lfOrientation; // 字符基线倾斜角度
LONG lfWeight; // 字体粗细
BYTE lfItalic; // 是否斜体
BYTE lfUnderline; // 是否下划线
BYTE lfStrikeOut; // 是否删除线
BYTE lfCharSet; // 字符集
BYTE lfOutPrecision; // 输出精度
BYTE lfClipPrecision; // 剪辑精度
BYTE lfQuality; // 输出质量
BYTE lfPitchAndFamily; // 字体间距与族
TCHAR lfFaceName[32]; // 字体名称
} LOGFONT, *PLOGFONT;
二、成员详解
1. 字体尺寸与方向
-
lfHeight
以逻辑单位(如像素)指定字体高度,计算公式:
lfHeight = -MulDiv(点数, 屏幕DPI, 72)
。负值表示高度绝对值匹配,正值允许系统调整。 -
lfWidth
字符平均宽度,0 表示自动适配。若需固定宽度(如等宽字体),可设置为字符的像素宽度。 -
lfEscapement & lfOrientation
- Escapement:整行文本相对于基线的倾斜角度(单位:0.1度),常用于数学公式排版。
- Orientation:单个字符基线的倾斜角度。在 Windows NT 中可能与 Escapement 不同,用于垂直文本布局。
2. 字体样式
-
lfWeight
字体粗细(0~1000),常用值:FW_NORMAL
(400):常规FW_BOLD
(700):加粗- 0 表示默认粗细。
-
lfItalic / lfUnderline / lfStrikeOut
布尔值,分别控制斜体、下划线和删除线效果。
3. 字符集与编码
- lfCharSet
指定字符集,常用值:ANSI_CHARSET
:ANSI 编码GB2312_CHARSET
:简体中文OEM_CHARSET
:依赖系统本地设置DEFAULT_CHARSET
:根据系统区域自动选择。
4. 渲染精度与质量
-
lfOutPrecision
控制字体匹配的严格程度,常用值:OUT_DEFAULT_PRECIS
:默认匹配OUT_TT_PRECIS
:优先选择 TrueType 字体OUT_STROKE_PRECIS
:匹配矢量/光栅字体。
-
lfClipPrecision
定义字符溢出剪辑区域时的处理方式:CLIP_DEFAULT_PRECIS
:默认剪辑CLIP_STROKE_PRECIS
:仅剪辑光栅/矢量字体。
-
lfQuality
输出质量等级:ANTIALIASED_QUALITY
:抗锯齿(需字体支持)NONANTIALIASED_QUALITY
:禁用抗锯齿PROOF_QUALITY
:高保真,禁用缩放。
5. 字体族与间距
-
lfPitchAndFamily
低 2 位表示间距:FIXED_PITCH
:固定间距(如等宽字体)VARIABLE_PITCH
:可变间距
高 4 位表示字体族:FF_ROMAN
(衬线体)、FF_SWISS
(无衬线体)等。
-
lfFaceName
字体名称(如 "Arial"),最大长度 31 个字符(TCHAR[32])。若为空,系统按其他属性匹配默认字体。
三、典型应用场景
-
动态字体设置
通过CreateFontIndirect(&logFont)
创建字体对象,应用于控件(如按钮、编辑框)或 GDI 绘图。 -
字体枚举
使用EnumFontFamiliesEx
遍历系统字体,通过回调函数获取匹配的LOGFONT
。 -
自定义字体对话框
在CHOOSEFONT
结构体中填充LOGFONT
,实现字体选择功能。 -
文本特效渲染
结合lfEscapement
实现倾斜文本,或通过lfStrikeOut
绘制删除线效果。
四、注意事项
-
单位转换
- 逻辑单位需根据设备上下文(HDC)的映射模式(如
MM_TEXT
)转换为物理像素。 - 使用
GetDeviceCaps(hdc, LOGPIXELSY)
获取 DPI 以进行精确计算。
- 逻辑单位需根据设备上下文(HDC)的映射模式(如
-
字符集兼容性
- 跨语言应用需正确设置
lfCharSet
,避免乱码。 - 使用 Unicode 时,建议调用
LOGFONTW
版本。
- 跨语言应用需正确设置
-
字体匹配规则
- 系统会根据
lfOutPrecision
和lfClipPrecision
选择最接近的物理字体,可能忽略部分属性(如lfWeight
)。
- 系统会根据
-
内存管理
- 直接修改
lfFaceName
字符串时需确保以\0
结尾,避免越界。
- 直接修改
五、代码示例
// 创建粗体斜体 Arial 字体
LOGFONT lf = {0};
lf.lfHeight = 24; // 24 逻辑单位高
lf.lfWeight = FW_BOLD; // 加粗
lf.lfItalic = TRUE; // 斜体
_tcscpy_s(lf.lfFaceName, LF_FACESIZE, _T("Arial"));
HFONT hFont = CreateFontIndirect(&lf);
SendMessage(hWnd, WM_SETFONT, (WPARAM)hFont, TRUE);
六、扩展学习
- TrueType 与 OpenType:通过
lfOutPrecision=OUT_TT_PRECIS
强制使用矢量字体。 - 多语言支持:结合
lfCharSet
和 Unicode 编码处理复杂文本。 - 性能优化:避免频繁创建/销毁字体对象,建议复用
HFONT
。
通过深入理解 LOGFONT 的每个成员,开发者可以精准控制字体渲染效果,提升应用程序的视觉表现力。