如何避免Windows文本缩放变更时Screen.MenuFont设置被重置?
问题原因
VCL框架中Screen对象的MenuFont属于全局系统关联字体属性,和系统主题、DPI缩放逻辑深度绑定。当你在Windows显示设置中调整缩放比例时,系统会向所有进程发送WM_DPICHANGED消息,VCL收到该消息后会执行内部适配逻辑,自动将MenuFont、CaptionFont等全局字体重置为当前DPI下的系统默认字体配置,直接覆盖你在构造函数中一次性写入的自定义值。
哪怕后续将缩放比例调回原值,VCL的重置逻辑只会读取当前系统的默认菜单字体参数,不会恢复你之前的自定义配置,因此会出现字体无法复原的问题。
解决方案
- 拦截DPI变更消息重写字体配置
在主窗体的消息映射中添加WM_DPICHANGED消息的处理逻辑,每次收到消息先执行默认的VCL适配逻辑,再重新写入自定义的MenuFont配置,确保自定义值始终覆盖VCL的自动重置值,参考代码如下:
// 主窗体头文件中添加消息映射声明 BEGIN_MESSAGE_MAP MESSAGE_HANDLER(WM_DPICHANGED, TMessage, HandleDpiChanged) END_MESSAGE_MAP(TForm) // 消息处理函数实现 void __fastcall TMainForm::HandleDpiChanged(TMessage &Msg) { // 执行默认DPI适配逻辑 TForm::Dispatch(&Msg); // 重设自定义菜单字体 Screen->MenuFont->Name = "Segoe UI"; Screen->MenuFont->Size = 11; }
- 监听系统设置变更事件
如果需要覆盖所有系统设置变更导致的字体重置场景,你可以监听Application对象的OnSettingChange事件,在事件回调中重设MenuFont,适配范围比仅拦截DPI变更更广。 - 禁用高DPI感知(不推荐)
如果项目不需要适配高DPI缩放,可以直接在项目选项中关闭高DPI感知开关,此时系统不会发送DPI变更消息,VCL也不会触发全局字体重置逻辑,但该方案会导致程序在高缩放比例下显示模糊,仅可用于临时测试场景。
内容的提问来源于stack exchange,提问作者Kerem
相关产品推荐
相关产品推荐

