详细分析字体选择对话框代码
书籍:《Visual C++ 2017从入门到精通》的2.3.8 Win32控件编程
环境:visual studio 2022
内容:【例2.33】字体选择对话框。
说明:以下内容大部分来自腾讯元宝。
增加“字体选择对话框”菜单
在资源视图->对应项目->Menu->IDC_TEST233->点击“请在此处键入”->新增"字体选择对话框"菜单,增加好后,点击该菜单->属性->修改ID为"IDM_FONTDLG"。
处理IDM_FONTDLG消息
点击上述建立好的“字体选择对话框”菜单后,会触发与之关联的IDM_FONTDLG消息,在WM_COMMAND下处理该消息,主要内容是初始化CHOOSEFONT变量cf,调用ChooseFont(&cf)弹出字体选择对话框等待用户选择时,通过cf返回用户的选择结果并记录在在hfont和rgbCurrent中,以便在InvalidateRect()中触发的WM_PAINT更新显示所选择的效果。
case IDM_FONTDLG:
/*初始化结构体
作用:通过 ZeroMemory 清空 CHOOSEFONT 结构体 cf 的所有成员,确保初始状态一致。
关键参数:
lStructSize:显式设置结构体大小(sizeof(cf)),避免因系统版本差异导致的兼容性问题。*/
ZeroMemory(&cf, sizeof(cf));
/*设置对话框属性
** hwndOwner** :指定对话框的所有者窗口句柄 hWnd,确保对话框在屏幕上的正确位置显示。
** lpLogFont** :关联 LOGFONT 结构体 lf,用于存储用户选择的字体属性(如字体名称、字号、样式等)。
** rgbColors** :初始化当前文本颜色为 rgbCurrent,用户可在对话框中修改此颜色。*/
cf.lStructSize = sizeof(cf);
cf.hwndOwner = hWnd;
cf.lpLogFont = &lf;
cf.rgbColors = rgbCurrent;
/*配置对话框行为
** CF_SCREENFONTS** :限制对话框仅显示屏幕适配的字体,避免选择打印机专用字体导致显示异常。
** CF_EFFECTS** :启用颜色和字体效果(如下划线、删除线)的选择功能。*/
cf.Flags = CF_SCREENFONTS | CF_EFFECTS;
/*显示对话框并处理结果
** ChooseFont(&cf)** :
显示字体选择对话框,用户确认后返回非零值。
若用户取消操作,函数返回零,代码块不执行。
** CreateFontIndirect(cf.lpLogFont)** :
根据用户选择的 LOGFONT 结构体创建实际字体对象 hfont,供后续绘图使用。
** rgbCurrent = cf.rgbColors * *:更新当前颜色值为用户选择的新值。
* *InvalidateRect(hWnd, NULL, 1) * *:
标记窗口客户区为无效,触发重绘消息(WM_PAINT),使新字体和颜色立即生效。*/
if (ChooseFont(&cf))
{
hfont = CreateFontIndirect(cf.lpLogFont);
rgbCurrent = cf.rgbColors;
InvalidateRect(hWnd, NULL, 1);
}
break;
处理WM_PAINT消息
在WM_PAINT消息处理中,根据在IDM_FONTDLG中保存的用户选择的字体hfont及rgbCurrent来重新显示内容。
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: 在此处添加使用 hdc 的任何绘图代码...
/*保存并替换当前字体
作用:将当前选入设备上下文的字体替换为用户自定义字体hfont,并将原字体句柄保存至hfontPrev。
资源管理:SelectObject返回原对象句柄,需在绘制完成后恢复,防止GDI对象泄漏。
字体兼容性:若hfont是系统字体(如通过CreateFont创建),需确保其字符集与应用程序匹配(如ANSI_CHARSET或UNICODE_CHARSET)。*/
hfontPrev = (HFONT)SelectObject(hdc, hfont);
/*设置文本颜色
作用:将设备上下文的文本前景色设置为rgbCurrent,影响后续TextOut等函数的输出效果。
颜色范围:支持RGB颜色模式(0 - 255范围)和预定义系统颜色(如CLR_INVALID)。
注意事项:若未调用绘图函数(如TextOut),颜色设置不会生效。*/
SetTextColor(hdc, rgbCurrent);
/*输出文本
作用:在坐标(10, 20)处输出字符串sz,长度由_tcslen计算(适用于Unicode字符串)。
参数解析:
10, 20:文本左上角坐标(客户区坐标系)。
sz:待输出字符串的指针(需确保有效且以\0结尾)。
_tcslen(sz):计算字符串长度(_tcslen为宏,根据项目字符集自动选择strlen或wcslen)。*/
TextOut(hdc, 10, 20, sz, _tcslen(sz));
/*恢复原字体
作用:将设备上下文的字体恢复为hfontPrev,避免影响后续绘制操作。
必要性:若未恢复,后续使用默认字体的GDI函数可能因状态异常导致错误。*/
SelectObject(hdc, hfontPrev);
/*结束绘制并验证窗口
作用:结束当前绘制流程,通知系统无效区域已处理完毕,更新窗口显示。
关键性:必须成对使用BeginPaint和EndPaint,否则可能导致窗口重绘异常或资源泄漏。*/
EndPaint(hWnd, &ps);
}
break;
执行效果
1.编译执行程序,点击“字体选择对话框”。
2.配置
3.效果
相关内容
详细介绍LOGFONT 结构体-CSDN博客https://blog.csdn.net/qq_20725221/article/details/146340663?spm=1001.2014.3001.5501详细分析CHOOSEFONT结构体-CSDN博客
https://blog.csdn.net/qq_20725221/article/details/146332889?spm=1001.2014.3001.5501详细介绍SelectObject()-CSDN博客
https://blog.csdn.net/qq_20725221/article/details/146343322?spm=1001.2014.3001.5501详细分析SetTextColor()-CSDN博客
https://blog.csdn.net/qq_20725221/article/details/146343655?spm=1001.2014.3001.5501详细介绍ChooseFont()-CSDN博客
https://blog.csdn.net/qq_20725221/article/details/146344277?spm=1001.2014.3001.5501详细介绍HFONT结构体-CSDN博客
https://blog.csdn.net/qq_20725221/article/details/146346267?spm=1001.2014.3001.5501