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

bqf10yzr  于 2023-04-12  发布在  其他
关注(0)|答案(7)|浏览(289)

我已经用C#创建了一个简单的Winforms应用程序。当我在一台具有高DPI设置(例如150%)的机器上运行应用程序时,应用程序会放大。到目前为止一切顺利!但不是用更大的字体渲染字体,而是所有文本也会放大。这当然会导致非常模糊的文本(在所有控件上,如按钮等)。
windows不应该正确地处理文本的渲染吗?例如,我的应用程序的标题栏渲染得很清晰。

rvpgvaaj

rvpgvaaj1#

一旦超过100%(或125%,勾选“XP风格DPI缩放”复选框),Windows默认接管UI的缩放。它通过让应用将其输出呈现为位图并将该位图绘制到屏幕上来实现。重新缩放该位图会使文本不可避免地看起来模糊。一个称为“DPI虚拟化”的功能,它可以使旧程序在高分辨率显示器上可用。
您必须明确地让它知道您可以通过将<dpiAware>元素添加到清单来处理更高的DPI设置。MSDN页面is here,但它不完整,因为它忽略了UAC设置。Project + Add New Item,选择“Application Manifest File”。编辑清单文本或复制/粘贴以下内容:

<?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()方法中pinvoke 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 Update 1或更高版本,这个常见的需求最终会更容易一些。添加的清单已经有了相关的指令,只需删除注解。
关键字搜索,这样我就可以找到这篇文章回来:dpiAware

qlfbtfca

qlfbtfca2#

可以在两种不同的模式下开发应用程序。
第一个是声明我们的应用程序是非DPI感知的(不声明任何东西将默认为这个)。在这种情况下,操作系统将在预期的96 DPI下渲染我们的应用程序,然后将我们之前讨论的位图缩放。结果将是一个模糊的应用程序,但具有正确的布局。
第二个选项是将应用程序声明为DPI感知。在这种情况下,操作系统将不会进行任何缩放,并将让您的应用程序根据屏幕的原始DPI进行渲染。在每显示器DPI环境的情况下,您的应用程序将以所有屏幕中最高的DPI进行渲染,然后这个位图将被缩小到每个显示器的适当大小。2缩小比放大会带来更好的观看体验,但你可能仍然会注意到一些模糊。
如果你想避免这种情况,你必须将你的应用程序声明为per-monitor-DPI-aware。然后你必须检测你的应用程序何时被拖动到不同的显示器上,并根据当前显示器的DPI进行渲染。
在清单文件中声明DPI感知。
参考以下链接stackoverflow

bqucvtff

bqucvtff3#

使用.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窗体应用程序启动后更改DPI或比例因子。
来源:High DPI support in Windows Forms

btxsgosb

btxsgosb4#

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

dgiusagp

dgiusagp5#

至少在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>
ee7vknir

ee7vknir6#

这不是一个答案。这是我的工作。上面的答案或评论对我都不起作用。我还搜索并尝试了其他方法。
我一直在使用Visual Studio.NET与C#和Windows.Forms,因为它最初发布。直到今年VS 2022和Windows 11,设置缩放模式似乎工作正常。由于某种原因,我的Form.Height值在运行时减少。到目前为止,Form.Width没有问题。对我来说,这个问题始于4月1日,2022年-所以我第一次以为这是一个愚人节的恶作剧!
无论如何,我现在已经放弃了尝试 * 解决方案 *,并决定在构造函数代码中设置Form.Size对我来说更实用。
我观察到Designer UI使用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专业版
  • Microsoft Visual Studio Professional 2022
  • 版本17.1.6
  • VisualStudio.17.Release/17.1.6+32421.90
  • Microsoft .NET Framework版本4.8.04161
  • C#工具4.1.0-5.22165.10+ e555772 db 77 ca 828 b 02 b4 bd 547 c318387 f11 d 01 f
  • HDMI 1920 x1080视频(100%或无缩放)
gg0vcinb

gg0vcinb7#

多年来,我一直在与之斗争。有时候我做的改变奏效了,有时候行不通了。现在我终于找到了一个适用于所有显示器的设置:
在您的app.config文件中,添加以下部分
你的屏幕在每台显示器上看起来都一样

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

相关问题