C# 如何将应用程序配置为在具有高DPI设置(例如150%)的机器上正确运行?

C# 如何将应用程序配置为在具有高DPI设置(例如150%)的机器上正确运行?,c#,winforms,fonts,dpi,dpi-aware,C#,Winforms,Fonts,Dpi,Dpi Aware,我用C#创建了一个简单的Winforms应用程序。当我在具有高DPI设置(例如150%)的机器上运行应用程序时,应用程序将按比例放大。到现在为止,一直都还不错! 但是,所有文本也只是按比例放大,而不是以更大的字体大小呈现字体。这当然会导致非常模糊的文本(在所有控件上,如按钮等) windows不应该正确呈现文本吗?例如,我的应用程序的标题栏呈现清晰明了。一旦超过100%(或勾选“XP样式DPI缩放”复选框达到125%),默认情况下Windows将接管UI的缩放。它通过让应用程序将其输出渲染为位图

我用C#创建了一个简单的Winforms应用程序。当我在具有高DPI设置(例如150%)的机器上运行应用程序时,应用程序将按比例放大。到现在为止,一直都还不错! 但是,所有文本也只是按比例放大,而不是以更大的字体大小呈现字体。这当然会导致非常模糊的文本(在所有控件上,如按钮等)

windows不应该正确呈现文本吗?例如,我的应用程序的标题栏呈现清晰明了。

一旦超过100%(或勾选“XP样式DPI缩放”复选框达到125%),默认情况下Windows将接管UI的缩放。它通过让应用程序将其输出渲染为位图并将该位图绘制到屏幕上来实现。位图的重新缩放使文本不可避免地看起来模糊。一种称为“DPI虚拟化”的功能使旧程序可以在高分辨率显示器上使用

您必须明确地让它知道,您可以通过向清单中添加
元素来处理更高的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>

更新,如果使用VS2015更新1或更高版本,这种常见需求最终会变得更容易。添加的清单已经有相关的指令,只需删除注释即可



搜索关键字以便我能找到这篇文章:dpiAware应用程序可以在两种不同的模式下开发

第一个是声明我们的应用程序不支持DPI(默认情况下,不声明任何内容)。在这种情况下,操作系统将以预期的96 DPI呈现我们的应用程序,然后对我们之前讨论过的位图缩放进行处理。结果将是一个外观模糊的应用程序,但布局正确

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

如果要避免这种情况,必须根据monitor DPI aware声明应用程序。然后,必须检测应用程序何时跨不同的监视器拖动,并根据当前监视器的DPI进行渲染

在清单文件中声明DPI感知


参考以下链接

这些建议对我都不起作用,但是,在我删除
表单后发生了一些事情。Font=new
。。。从
Form.Design.cs
开始,表单开始正确地重新缩放,如果在构造函数中定义字体或根本不定义字体,则它可以工作。为什么?其他人可能可以解释,我只是可以谈论我所做的更改,并花了几分钟时间找出它是我正在处理的表单的根本原因。希望有帮助。

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

声明与Windows 10的兼容性。

为此,请将以下内容添加到
清单
文件中:

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

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

调用静态EnableVisualStyles方法。

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

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());   
}
这样做的好处是支持动态DPI场景,用户在启动Windows窗体应用程序后更改DPI或比例因子


来源:

至少从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>

真的

谢谢,您的解决方案运行良好。剩下的唯一问题是,所有图像现在都处于原始大小。我想我必须想办法在我的GUI中添加额外的“视网膜”图标…@HansPassant我也有同样的问题,字体模糊,应用此解决方案后,我的控件无法缩放,无法适应。如何让这两个都工作?对于任何调查这一Win8疯狂的人来说,
SetProcessDPIAware
是不推荐的,而且它也不能正常工作(至少在Win8.1中不能),导致不同控件上的不可预测的缩放。我强烈建议改为使用清单方法。Hmya,每个监视器DPI获取Windows 8.1。我不知道我需要它。如果要使用ClickOnce进行部署,则不能使用清单中的dpiAware选项,请改用SetProcessDPIAware()。如果用户有一个还原大小的窗口,并将其移动,使其部分位于不同的监视器上,该怎么办?我们是否需要渲染所有内容两次并使用监视器边界作为边界框?winforms库包含了多少内容?
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form1());   
}
<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
</application>