
WPF Per Monitor DPI 完整适配指南3 步解决多显示器缩放模糊【免费下载链接】WPF-SamplesRepository for WPF related samples项目地址: https://gitcode.com/gh_mirrors/wp/WPF-Samples本文带你过一遍 WPF-Samples 的 WPF Per Monitor DPI 适配流程app.manifest 开 dpiAwareness、App.Config 配开关、接 DpiChanged 事件、备好多尺寸图片。照做就能修掉窗口跨屏后文字发虚、图片变糊的老毛病 ✅问题场景多屏 DPI 不一致界面为什么会糊两块显示器左 100%、右 150% 缩放。窗口拖到右边那块图标发虚、文字毛糙。原因WPF 默认只有 System DPI 感知——窗口按主屏缩放整体绘制跨到别的屏幕时系统只能拉伸或压缩整张位图。拉大就糊压缩就浪费分辨率。原理速览Per Monitor DPI 到底是什么Per Monitor DPI每显示器 DPI 感知随 .NET 4.6.2 和 Windows 10 周年更新引入。意思很直白系统把窗口所在屏幕的真实缩放比例告诉应用应用按这个比例自己重绘内容。启用后窗口跨屏会自动切到目标缩放下原生渲染不再拉伸位图。纯 WPF 内容配好两个文件即可图片、宿主控件、底层文本 API 还要补几行代码。上手三步配置 dpiAwareness 并跑通跨屏验证第 1 步app.manifest 开启 PerMonitor 感知 ✅项目里新建 app.manifest右键项目 - 添加 - 新建项 - 应用程序清单文件补上这两个标签新标签在 Windows 10 周年更新及以上生效老标签给旧系统兜底。application xmlnsurn:schemas-microsoft-com:asm.v3 windowsSettings dpiAwareness xmlnshttp://schemas.microsoft.com/SMI/2016/WindowsSettingsPerMonitor/dpiAwareness dpiAware xmlnshttp://schemas.microsoft.com/SMI/2005/WindowsSettingstrue/dpiAware /windowsSettings /application第 2 步App.Config 加 WPF 侧开关 ✅目标框架低于 .NET 4.6.2 才需要这一步加在 App.Config 的 configuration 节里runtime AppContextSwitchOverrides valueSwitch.System.Windows.DoNotScaleForDpiChangesfalse/ /runtime两个坑它叫 DoNotScale 却要设成 false双重否定才算开AppContextSwitchOverrides 一个文件只能出现一次已有就分号分隔追加。第 3 步拖窗口做第一次跨屏验证 编译运行把窗口在两块不同缩放的显示器间来回拖。文字锐利、控件自动跟随新屏缩放基础配置就通了。运行时响应窗口跨屏时监听 DpiChanged 事件布局会自动跟随缩放但换图片、重缩放宿主控件得你自己接事件 ⚡ 速查表如下API什么时候用Window.DpiChanged窗口移到不同缩放显示器时触发作为整窗内容重排或重渲染的主入口Image.DpiChanged路由事件窗口内每个 Image 都收到换入对应缩放图片可在 XAML 根上集中监听WindowsFormsHost.DpiChanged每个宿主控件都会触发算出新旧缩放比后对子控件调Control.ScaleVisualTreeHelper.GetDpi(visual)静态方法返回DpiScale随时查某个视觉当前的渲染 DPIVisualTreeHelper.SetRootDpi(visual, dpi)仅无父级的根视觉可调RenderTargetBitmap渲染树外视觉前声明目标 DPI查当前 DPI 一行搞定DpiScale dpi VisualTreeHelper.GetDpi(myImage);WinForms 宿主的完整做法参考 PerMonitorDPI/WinFormsHost/ 示例在 DpiChanged 里算 NewDpi 与 OldDpi 的 PixelsPerDip 之比传给托管控件的 Scale字体同步放大。资源准备图片按 100/200/400 三档备齐 ️同一张图备 100%、200%、400% 三档命名统一成 scale-100.png 这种格式。运行时读当前 PixelsPerDip取最接近且不小于它的那档加载——微软的建议是宁缩勿放所以留三档而不是两档。PerMonitorDPI/ImageScaling/ 示例做了个 DpiAwareImage 控件首次加载用 GetDpi 选图重写 OnDpiChanged 后每次缩放变化再换一次 Source思路可以直接抄。文本侧用 FormattedText、TextSource 这类 API 自绘文字时要把目标 DPI 经新增的 PixelsPerDip 传进去DPI 变化时强制重排重绘对照 PerMonitorDPI/TextFormatting/ 示例即可。验收清单测试环境与自检查项测试环境要求Windows 10 周年更新或更高版本两块不同缩放的显示器如 100% 与 150%自检查项拖窗跨屏目标缩放下文字锐利无整体拉伸感含图片跨屏后自动换到对应 scale 资源含 WinForms 宿主跨屏后子控件尺寸、字体按比例跟随用 RenderTargetBitmap 的渲染前调用 SetRootDpi 声明目标 DPIApp.Config 里 AppContextSwitchOverrides 仅出现一次多开关分号分隔用到新 API 的项目已把目标框架升到 .NET 4.6.2已知限制WinForms 应用经 ElementHost 托管 WPF、Win32 窗口经 HwndSource 托管 WPF均不支持 Per Monitor DPI——WM_DPICHANGED 只发给顶层窗口WPF 收不到。 想动手直接打开 PerMonitorDPI/ 下的四个示例FormattedTextExample、ImageScaling、TextFormatting、WinFormsHost各对应本文一个场景。边跑边拖屏验证最快。【免费下载链接】WPF-SamplesRepository for WPF related samples项目地址: https://gitcode.com/gh_mirrors/wp/WPF-Samples创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考