尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SunnyUI WinForm DPI 缩放自适应方案:三步配置实现窗体和字体不变形

SunnyUI WinForm DPI 缩放自适应方案:三步配置实现窗体和字体不变形 UI组件桌面应用【免费下载链接】SunnyUISunnyUI.NET 是基于.NET Framework 4.0、.NET6、.NET8、.NET9 框架的 C# WinForm UI、开源控件库、工具类库、扩展类库、多页面开发框架。项目地址https://gitcode.com/gh_mirrors/su/SunnyUI点击查看免费下载在高分屏普及的今天Windows 的系统级 DPI 缩放会把 WinForm 窗体连同字体一起等比放大导致窗体布局错位、字体发虚变形界面美观度大打折扣。SunnyUI 提供了一套完整的 DPI 缩放自适应方案通过设置 AutoScaleMode、声明 dpiAware、开启 DPIScale三步配置即可让窗体尺寸与字体在不同 DPI 缩放下均保持等比、不变形。读完本文你将掌握这套方案的完整落地步骤、app.manifest的正确写法以及其底层基于 UIDPIScale.cs 的字体缩放原理能够直接应用到自己的 SunnyUI 项目中。为什么 WinForm 窗体在 DPI 缩放时会变形WinForm 窗体在高分屏下出现窗体变形和字体变形根源在于操作系统设置的字体缩放。窗体默认AutoScaleMode Font当操作系统开启高分屏字体缩放后WinForm 控件会按照字体尺寸进行自动缩放控件位置、间距、大小随之拉伸最终表现为窗体布局错位变形。窗体没有声明 DPI 感知dpiAware未声明感知 DPI 的应用会被 Windows 当作非感知程序进行位图拉伸式缩放整个界面包括文字都会发虚、失真。字体尺寸没有按 DPI 反向补偿即使窗体本身等比放大了字体若不随之等比放大就会出现窗体变大了、字还是那么大或相反的不协调现象。SunnyUI 的 DPI 缩放自适应方案正是针对上述三个成因分三步逐一解决最终实现随着 DPI 缩放窗体和字体均不变形的目标。三步操作总览步骤操作实现目标1设置窗体和自定义用户控件的AutoScaleMode为None禁止窗体因字体大小缩放而变形2设置app.manifest的dpiAware为true禁止窗体因 DPI 缩放而变形3设置UIStyleManager.DPIScale为trueDPI 缩放后字体大小不变形以下逐一展开说明。第一步设置 AutoScaleMode 为 None由于高分屏下操作系统设置了字体缩放窗体默认的AutoScaleMode Font会导致控件因字体自动缩放而变形。解决方法是把窗体和用户控件的AutoScaleMode设置为None从当前仓库的源码可以确认SunnyUI 已经内置了这一步UIForm.cs 的版本记录明确写到2022-04-02: V3.1.2 默认设置AutoScaleMode为NoneUIBaseForm.cs 在OnShown中做了强制兜底if (AutoScaleMode AutoScaleMode.Font) AutoScaleMode AutoScaleMode.None;UIUserControl.cs 同样在构造函数中默认写入AutoScaleMode AutoScaleMode.None;并且第 363365 行会在检测到Font模式时自动纠正各内置控件的 Designer 文件中也都显式声明了AutoScaleMode System.Windows.Forms.AutoScaleMode.None例如 UIComboBox.Designer.cs、UITextBox.Designer.cs、UIDatePicker.Designer.cs。也就是说使用UIForm、UIPage、UIUserControl等 SunnyUI 基类时无需再手动设置。需要注意如果项目中直接使用了系统的自定义用户控件UserControl则必须手动将其AutoScaleMode设置为None否则该控件仍会在 DPI 缩放下被字体带偏。第二步设置 app.manifest 的 dpiAware 为 true为了让 Windows 不再对窗体进行位图拉伸式的粗放缩放需要显式声明应用程序感知 DPI。右键工程 → 添加 → 新建项 → 应用程序清单文件app.manifest使用默认文件名此时工程文件中会增加app.manifest然后取消application节点的注释按下面的内容修改启用dpiAware!-- 指示该应用程序可感知 DPI 且 Windows 在 DPI 较高时将不会对其进行 自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI无需 选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应 在其 app.config 中将 EnableWindowsFormsHighDpiAutoResizing 设置设置为 true。 将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -- application xmlnsurn:schemas-microsoft-com:asm.v3 windowsSettings dpiAware xmlnshttp://schemas.microsoft.com/SMI/2005/WindowsSettingstrue/dpiAware longPathAware xmlnshttp://schemas.microsoft.com/SMI/2016/WindowsSettingstrue/longPathAware /windowsSettings /application仓库中的 SunnyUI.Demo/app.manifest 即为配置完成后的真实范例dpiAware与longPathAware均设置为true同时保留requestedExecutionLevel levelasInvoker见第 18 行。两点补充说明.NET Framework 4.6及以上目标的 WinForms 应用若需要在 DPI 变化时自动调整窗体尺寸High DPI Auto-Resizing还应在app.config中把EnableWindowsFormsHighDpiAutoResizing设置为true清单注释中已给出提示。longPathAware顺手开启可让程序支持超过 260 字符的长路径避免资源文件路径过长导致的加载失败。第三步设置 DPIScale 为 true前两步解决的是窗体形状问题第三步解决字体大小问题DPI 缩放后SunnyUI 会按缩放比例反向补偿字体尺寸让字体始终保持与设计时一致的视觉大小。操作方式在编译时确认屏幕 DPI 缩放为 100%在主窗体上放置UIStyleManager控件选中该控件在属性面板的SunnyUI分类下把DPIScale设置为trueDPIScale属性定义在 UIStyleManager.cs 中属性值为bool类型默认false读写均直接映射到静态类UIStyles的全局开关UIStyles.DPIScaleUIStyles.cs因此它对整个应用全局生效而不是只作用于单个窗体。源码原理DPI 缩放字体补偿是如何实现的这一小节从源码层面拆解第三步背后的工作机制帮助你理解为什么在 100% DPI 下编译却能在任意 DPI 下不变形。1. 系统 DPI 缩放比例的测量UIDPIScale.cs 中的SystemDPIScale通过创建一个 1×1 的Bitmap并读取其图形对象的水平 DPI 来计算实际缩放比例using Bitmap bmp new Bitmap(1, 1); using Graphics g bmp.Graphics(); dpiScale g.DpiX / 96.0f;即以 96 DPI100% 缩放为基准系统 DPI 为 144 时比例即为1.5。2. 是否需要补偿字体的判定NeedSetDPIFont()的判定条件是UIDPIScale.cspublic static bool NeedSetDPIFont() UIStyles.DPIScale (SystemDPIScale 1 || UIStyles.GlobalFont);即必须开启UIStyles.DPIScale且要么系统 DPI 大于 100%要么开启了全局字体GlobalFont功能才需要进行字体补偿。这解释了文档强调的确认编译时 DPI 缩放为 100%——设计时的字体尺寸被记录下来运行时再根据当前系统 DPI 反向缩放。3. 字体的反向缩放公式核心方法DPIScaleFontUIDPIScale.cs的逻辑很直观用设计字号除以 DPI 缩放比例构造出物理上看起来与设计时一致大小的新字体if (UIStyles.GlobalFont) { byte gdiCharSet UIStyles.GetGdiCharSet(UIStyles.GlobalFontName); return new Font(UIStyles.GlobalFontName, fontSize / DPIScale, font.Style, font.Unit, gdiCharSet); } else { return new Font(font.FontFamily, fontSize / DPIScale, font.Style, font.Unit, font.GdiCharSet); }当未开启全局字体时保持原字体族仅字号除以DPIScale当开启全局字体时UIStyles.GlobalFont统一使用GlobalFontName默认宋体见 UIStyles.cs并带出该字体对应的 GDI 字符集GetGdiCharSet保证中文等字符渲染正确DPIScale的完整定义UIDPIScale.cs为GlobalFont ? SystemDPIScale * 100.0f / UIStyles.GlobalFontScale : SystemDPIScale即开启全局字体时还会叠加GlobalFontScale默认 100UIStyles.cs的全局字号缩放因子用于整体调整全局字体大小。4. 窗体与页面的递归应用UIStyles.SetDPIScale()UIStyles.cs遍历所有已注册的窗体和页面逐个调用form.SetDPIScale()/page.SetDPIScale()。以窗体为例UIBaseForm.cs 的SetDPIScale做了三件事首次调用时记录设计字号DefaultFontSize、TitleFontSize对窗体自身字体与标题字体执行SetDPIScaleFont/DPIScaleFont通过GetAllDPIScaleControls()UIDPIScale.cs递归收集窗体下所有实现IStyleInterface的控件逐一调用control.SetDPIScale()完成字体补偿。GetAllDPIScaleControls中还会跳过UITextBox、UIDropControl、UIListBox、UIRichTextBox、UITreeView等内部自带滚动/绘制逻辑的复合控件见 UIDPIScale.cs避免重复或错误的字体设置。整个调用链在窗体OnShownUIBaseForm.cs时自动触发无需开发者手动调用。编译与验证方法完成上述三步后按以下流程编译和验证确认编译时屏幕的 DPI 缩放为 100%显示设置 → 缩放与布局 → 100%编译程序将系统 DPI 分别调整到 125%、150% 等不同档位重新运行编译好的程序可参考仓库中的 SunnyUI.Demo 示例工程 进行对比测试观察窗体布局与字体布局不错位、字体不发虚即为配置成功。值得说明的是这套方案配合 UIZoomScale.csZoomScale缩放与 UIStyles.cs 中的GlobalFontName全局字体机制一起使用可以同时控制控件整体缩放与全局统一字体适合需要精细化适配的应用。常见问题自定义 UserControl 仍然变形因为 SunnyUI 只保证内置基类默认AutoScaleMode None自定义控件需手动设置参见第一步。只做了前两步、字体依然发虚请检查第三步是否完成——UIStyleManager是否已放置、DPIScale是否为true且NeedSetDPIFont的判定依赖UIStyles.DPIScale全局开关。编译环境 DPI 不是 100%字体补偿以编译时字号为基准若编译时系统 DPI 非 100%记录的基准字号已偏移可能导致运行时字体偏大或偏小因此务必在 100% DPI 下编译。.NET Framework 4.6目标下窗体尺寸不随 DPI 自动调整按app.manifest注释要求在app.config中开启EnableWindowsFormsHighDpiAutoResizing。以上三步就是 SunnyUI DPI 缩放自适应方案的完整闭环AutoScaleMode 关掉字体缩放干扰 → dpiAware 声明感知 DPI → DPIScale 按系统 DPI 反向补偿字体三者缺一不可组合使用即可在高分屏上获得与设计时一致的界面效果。赞分享UI组件桌面应用【免费下载链接】SunnyUISunnyUI.NET 是基于.NET Framework 4.0、.NET6、.NET8、.NET9 框架的 C# WinForm UI、开源控件库、工具类库、扩展类库、多页面开发框架。项目地址https://gitcode.com/gh_mirrors/su/SunnyUI点击查看免费下载相关推荐Rainmeter皮肤字体大小适配DPI缩放处理技巧Rainmeter皮肤字体大小适配DPI缩放处理技巧 痛点直击为什么你的皮肤在高DPI下总是错位 当Windows系统DPI缩放比例超过100%时你是否桌面应用LocalSend字体缩放动态字体大小适配方案LocalSend字体缩放动态字体大小适配方案 痛点场景多设备适配的字体挑战 在日常跨设备文件传输中你是否遇到过这样的困扰在手机上字体太小看不清在平板即时通讯网络/通信xrdp与Wayland高DPI支持缩放与字体配置xrdp与Wayland高DPI支持缩放与字体配置 痛点直击高分辨率屏幕下的xrdp显示难题 你是否在4K显示器上使用xrdp时遭遇过界面模糊、字体过小或元后端网络通信上一篇3步彻底解决Windows C盘空间不足的智能清理方案下一篇ExoPlayer 主 Demo 应用demo 模块源码解析与构建运行实践指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表