How to configure an app to run correctly on a machine with a high DPI setting (e.g. 150%)?

我用 C # 创建了一个简单的 Winforms 应用程序。当我在高 DPI 设置(例如150%)的机器上运行应用程序时,应用程序的规模会扩大。目前为止一切顺利! 但是,不是渲染的字体与较高的字体大小,所有文本只是放大,也。这当然会导致非常模糊的文本(对所有控件,如按钮等)。

Shouldn't windows take care of rendering the texts correctly? For example my application's title bar is rendered crisp & clear.

57133 次浏览

一旦超过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();

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


关键字搜索,所以我可以找到这篇文章回: dpiAware

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

第一种方法是将我们的应用程序声明为不支持 DPI (不声明任何内容将默认为此)。在这种情况下,操作系统将在 expected 96 DPI下呈现我们的应用程序,然后处理我们之前讨论过的位图缩放。结果将是一个看起来模糊的应用程序,但有一个正确的布局。

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

如果希望避免这种情况,则必须将应用程序声明为 per-monitor-DPI-aware。然后,必须检测应用程序何时被拖动到不同的监视器上,并根据当前监视器的 DPI 进行渲染。

在清单文件中声明 DPI 感知。

请参考以下连结 堆栈溢出

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

吸毒。NET Framework 4.7和 Windows 10 Creators Update (1703)或更新版本必须执行以下操作才能为 Windows Form 应用程序配置高 DPI 支持:

声明与 Windows10的兼容性

为此,在 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 框架,使用清单添加高 DPI 支持。不再推荐使用这种方法,因为它覆盖了 app.config 文件中定义的设置。

调用静态 EnableVisualStyles 方法。

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

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

这样做的好处是支持动态 DPI 场景,在这些场景中,用户在启动 Windows 窗体应用程序后更改 DPI 或缩放因子。

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

至少从 VisualStudio2017开始,您只需要添加一个清单文件并取消注释此部分:

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

这不是答案。这是我的工作。以上的回答和评论对我都不起作用。我还寻找和尝试了其他方法。

我一直在 C # 和 Windows 中使用 Visual Studio. NET。表单,因为它最初发布。直到今年 VS2022和 Windows11之前,设置缩放模式看起来还不错。由于某种原因,一些的我的形式。高度值在运行时减少。表格至今没有问题。宽度正在改变。对我来说,这个问题始于2022年4月1日——所以我一开始以为这是愚人节的恶作剧!

无论如何,我已经放弃了尝试 解决方案现在,并决定它是更实际的为我设置的形式。构造函数代码中的大小。

我观察到 Designer UI 使用 Size,它在生成的代码中将 Size转换为 ClientSize,如下所示:

  this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.ClientSize = new System.Drawing.Size(744, 109);
this.ControlBox = false;
this.DoubleBuffered = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;

我在 Form 构造函数中的工作区如下:

/// <summary>
/// Constructor
/// </summary>
public MyForm()
{
// In the designer, MyForm.Size was entered and displayed as 760, 148
InitializeComponent();


// At runtime, MyForm.Size is changed to 760, 111
// I will Reset this form's Size here so I can get full height again.
this.Size = new Size(760, 148);
}

平台:

  • Windows 11 Professional
  • MicrosoftVisualStudioProfessional2022
  • 版本17.1.6
  • VisualStudio. 17. Release/17.1.6 + 32421.90 VisualStudio. 17. Release/17.1.6 + 32421.90
  • Microsoft. NET Framework 版本4.8.04161
  • C # Tools 4.1.0-5.22165.10 + e555772db77ca828b02b4bd547c318387f11d01f
  • HDMI 1920x1080视频(100% 或无缩放)