如何配置一个应用程序使其在具有较高DPI设置(例如150%)的计算机上正确运行?


101

我已经在C#中创建了一个简单的Winforms应用程序。当我在具有较高DPI设置(例如150%)的计算机上运行该应用程序时,该应用程序会按比例放大。到目前为止,一切都很好!但是,除了渲染具有更大字体大小的字体外,所有文本也都按比例放大。当然,这会导致文本非常模糊(在按钮等所有控件上)。

Windows是否应该照顾正确呈现文本?例如,我的应用程序的标题栏变得清晰明了。

Answers:


131

一旦超过100%(或选中“ XP样式DPI缩放比例”复选框为125%),Windows默认将接管UI的缩放比例。通过让您的应用将其输出呈现为位图并将该位图绘制到屏幕上来实现。该位图的重新缩放使文本不可避免地变得模糊。一种称为“ DPI虚拟化”的功能,可以使旧程序在高分辨率监视器上可用。

您必须明确告知它,可以通过将<dpiAware>元素添加到清单中来处理更高的DPI设置。MSDN页面在这里,但是由于它省略了UAC设置,所以它并不完整。项目+添加新项,选择“应用程序清单文件”。编辑清单文本或复制/粘贴以下内容:

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
    <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
    <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

您还可以在Main()方法中固定SetProcessDPIAware(),例如,如果使用ClickOnce进行部署,则是必需的:

    [STAThread]
    static void Main() {
        if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());             // Edit as needed
    }

    [System.Runtime.InteropServices.DllImport("user32.dll")]
    private static extern bool SetProcessDPIAware();

UPDATE,如果您使用VS2015 Update 1或更高版本,则此通用需求最终会更容易一些。添加的清单已具有相关指令,只需删除注释即可。


搜索的关键字,因此我可以找到该帖子:dpiAware


谢谢,您的解决方案工作正常。剩下的唯一问题是所有图像现在都保持其原始大小。我想我必须找到一种方法来向我的GUI添加其他“视网膜”图标...
Boris

@HansPassant我也遇到字体模糊的问题,应用此解决方案后,我的控件无法缩放且无法容纳。如何使两者同时工作?
gajo357 2014年

2
对于研究此Win8疯狂的任何人,SetProcessDPIAware它已被弃用,并且也无法正常工作(至少在Win8.1中不起作用),从而导致不同控件上的缩放比例无法预测。我强烈建议改为使用清单方法。
杰森·威廉姆斯

5
Hmya,Windows 8.1获得了每个监视器的DPI。我不知道我需要那个。
汉斯·帕桑

1
如果要使用ClickOnce进行部署,则不能使用清单中的dpiAware选项,而应使用SetProcessDPIAware()。
马蒂亚斯·

17

可以以两种不同的模式开发应用程序。

第一个是声明我们的应用程序不支持DPI(不声明默认值)。在这种情况下,操作系统将以预期的96 DPI渲染我们的应用程序,然后执行我们之前讨论的位图缩放。结果将导致应用程序外观模糊,但布局正确。

第二种选择是将应用程序声明为支持DPI。在这种情况下,操作系统将不会进行任何缩放,并将让您的应用程序根据屏幕的原始DPI进行渲染。如果是每个监视器的DPI环境,则将以所有屏幕中最高的DPI呈现您的应用程序,然后将该位图按比例缩小到每个监视器的适当大小。缩小比例比放大比例可带来更好的观看体验,但您可能仍会注意到一些模糊性。

如果要避免这种情况,则必须将您的应用程序声明为可识别每个监视器的DPI。然后,您必须检测何时将应用程序拖到不同的监视器上,并根据当前监视器的DPI进行渲染。

声明DPI感知是在清单文件中完成的。

请参考以下链接 stackoverflow


如果用户的窗口大小已还原并移动以使窗口的一部分位于不同的显示器上怎么办?我们是否需要将所有内容渲染两次并使用监视器边界作为边界框?winforms库涵盖了其中的多少?
Cee McSharpface '18 -10-11

4

使用.NET Framework 4.7和Windows 10 Creators Update(1703)或更高版本,您必须执行以下操作来为Windows Form应用程序配置高DPI支持:

声明与Windows 10的兼容性。

为此,将以下内容添加到您的manifest文件中:

<compatibility xmlns="urn:schemas-microsoft.com:compatibility.v1">
  <application>
    <!-- Windows 10 compatibility -->
    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
  </application>
</compatibility>

app.config文件中启用每个监视器的DPI感知。

Windows窗体引入了新的System.Windows.Forms.ApplicationConfigurationSection元素,以支持从.NET Framework 4.7开始添加的新功能和自定义项。要利用支持高DPI的新功能,请将以下内容添加到您的应用程序配置文件中。

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

重要

在.NET Framework的早期版本中,您使用清单添加了高级DPI支持。不再建议使用此方法,因为它会覆盖app.config文件中定义的设置。

调用静态的EnableVisualStyles方法。

这应该是应用程序入口点中的第一个方法调用。例如:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());   
}

这样做的好处是支持动态DPI方案,在这种方案中,用户在启动Windows Forms应用程序后更改DPI或比例因子。

来源:Windows窗体中的高DPI支持


3

这些建议对我都不起作用,但是,当我从Form.Font = new...中删除... 之后,发生了一些事情Form.Design.cs,该表单开始正确地重新缩放,无论是否在构造函数中定义了Font,此表单都可以工作。为什么?也许其他人可以解释,我只可以谈论我所做的更改,花了我几分钟的时间才弄清楚这是我正在处理的表格的根本原因。希望能帮助到你。


2

由于至少是Visual Studio 2017,因此您只需要添加清单文件并取消注释此部分即可:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
</application>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.