使 WinForms 和 WPF 支持高 DPI(每显示器缩放/2018年)

本文介绍了如何使WinForms和WPF应用支持高DPI,包括在不同显示器之间保持清晰显示。针对WPF,文章详细说明了在应用程序清单文件中启用Per Monitor DPI awareness的步骤,以及对.NET Framework 4.6.2以下版本的额外修改。对于WinForms,文章指导了声明Windows 10兼容性,启用每显示器DPI感知,以及处理与DPI相关的像素值。

前言

WinForms 和 WPF 都支持高 DPI,但是在默认情况下,不是未开启,就是效果不尽人意。例如,默认情况下,WPF 程序在单个高分屏上表现良好,但是如果把窗口拖动到不同的窗口上去,就会变得模糊。

关于不同的 DPI 缩放(感知)类型,请在此查看:https://docs.microsoft.com/zh-cn/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows

环境

  • Windows 10 1809
  • .NET Framework 4.7.2
  • Visual Studio 2017 15.9.4

所用环境是发文时最新稳定版。条件所限,其他环境请自行测试。

WPF

默认情况下,WPF 只支持单显示器的 DPI 缩放,在移动到缩放比例不同的显示器时,仍使用系统缩放,导致模糊。下面介绍开启Per monitor DPI awareness的方法。

1. 在 app.manifest 中开启 Per monitor DPI awareness

为了支持 Per monitor DPI awareness,需要修改 app.manifest 文件。如果你的项目没有这个文件,请新建应用程序清单文件,名称保持默认的 app.manifest

找到清单文件中的这一段:

  <!-- 指示该应用程序可以感知 DPI 且 Windows 在 DPI 较高时将不会对其进行
       自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI,无需
       选择加入。选择加入此设置的 Windows 窗体应用程序(目标设定为 .NET Framework 4.6 )还应
       在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。-->

  <!--<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>-->

可以看到提到了 DPI 感知,但其实上面这部分内容已经有点过时。
我们把下半部分替换成:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
    </windowsSettings>
  </application>

2. 修改 App.config (4.6.2 及以上不需要)

对于 .NET Framework 4.6.2 以下的版本,还需要修改 App.config 文件。下面是未更改的原始文件。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
    </startup>
</configuration>

将其更改为

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1"/>
    </startup>
  <runtime>
    <AppContextSwitchOverrides value = "Switch.System.Windows.DoNotScaleForDpiChanges=false"/>
  </runtime>
</configuration>

请自行比较不同部分。

3. 测试应用

运行程序,在不同缩放比例的显示器之间拖动。

正常情况下,纯 WPF 部分应该完美缩放,其余部分可能无法完美支持。请根据您的应用自行取舍。

更多内部请查看文后的参考资料。

WinForms

WinForms 的设置与 WPF 有所不同,不能按照 WPF 的方式进行设置。

1. 声明与 Windows 10 的兼容性

app.manifest 文件中找到下面部分,并按示例取消注释。如果你的项目没有这个文件,请按上面的方法创建。

      <!-- Windows 10 -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

2. 启用每显示器 DPI 感知

修改 App.config,添加下面内容

<System.Windows.Forms.ApplicationConfigurationSection>
  <add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>

根据微软给出的文档,

在以前版本的 .NET Framework 中,你可以使用清单来添加高 DPI 支持。 不再建议使用此方法,因为它会替代在 app.config 文件中定义的设置。

3. 测试应用

WinForms 对高 DPI 的支持更差。通过 API 获取到的像素值是与 DPI 相关的。也就是说,同样窗口大小,在不同显示器上会获取到不同的像素值。你必须手动处理。

参考资料

https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI

https://docs.microsoft.com/zh-cn/dotnet/framework/winforms/high-dpi-support-in-windows-forms

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值