vb.net WinForms 4K 和 1080p 缩放/高 DPI?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49012233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 20:23:06  来源:igfitidea点击:

WinForms 4K and 1080p scaling / high DPI?

.netvb.netwinformsvisual-studiohighdpi

提问by Chris K

So, here is the scenario: I am trying to make all of my forms (which are Winforms) look good in 4K and 1080p also known as high-DPI or "dpi-aware". I (for the purpose of this question) have three forms: frmCompanyMasterEditwhich inherits from frmBaseEditwhich inherits from frmBase, which inherits form System.Windows.Forms.Form.

所以,这是一个场景:我试图让我的所有表单(即 Winforms)在 4K 和 1080p 下看起来都不错,也称为高 DPI 或“dpi-aware”。我(为了这个问题)有三种形式:frmCompanyMasterEdit继承自frmBaseEdit继承自frmBase,继承形式System.Windows.Forms.Form

I have tried the old way, by making my application DPI-aware in the manifest:

我尝试了旧方法,通过在清单中使我的应用程序 DPI 感知:

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

That way, other than minor anchoring issues which I can fix, the form looks perfect at 4K and looks just like that but a bit blurrier in 1080p. Here it is in 4K: 4K both old and new ways.

这样,除了我可以修复的轻微锚定问题之外,表格在 4K 下看起来很完美,看起来就像那样,但在 1080p 下有点模糊。这是 4K:4K 新旧两种方式

Anyway, so I scratch that and try it the new way described in .NET 4.7, targeting the 4.7 framework and adding the following code:

无论如何,所以我从头开始并尝试使用 .NET 4.7 中描述的新方法,针对 4.7 框架并添加以下代码:

to app.config

到 app.config

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

to app.manifest

到应用程序清单

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

and also taking the old code out of the app.manifest so as to not override the new .NET 4.7 way. I made sure to put the code in the appropriate places. So here the form looks good in 4K as the image above but now in 1080p it is very zoomed in as shown here: 1080p new way

并将旧代码从 app.manifest 中取出,以免覆盖新的 .NET 4.7 方式。我确保将代码放在适当的位置。所以这里的表格在 4K 中看起来不错,如上图,但现在在 1080p 中它非常放大,如下所示: 1080p new way

So either way, the form looks great in 4k other than minor anchoring issues, and it either (the old way) is the right size but a bit blurry in 1080p or is not blurry in 1080p but is really zoomed in. I also had to change these two lines in all the designer.vb files as shown below:

因此,无论哪种方式,除了轻微的锚定问题外,该表单在 4k 中看起来都很棒,并且它(旧方式)大小合适但在 1080p 中有点模糊,或者在 1080p 中不模糊但确实放大了。我也不得不更改所有designer.vb文件中的这两行,如下所示:

Me.AutoScaleDimensions = New System.Drawing.SizeF(96.0!, 96.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi

I don't know why I just can't get it looking appropriate in 1080p. Like I said, I am targeting the 4.7 .NET framework. I am running on the appropriate version of Windows 10 (Version 1709 / Creator's edition). The 1080p is scaled at 100%. Also, we do not have the resources to upgrade to WPF.

我不知道为什么我不能让它在 1080p 下看起来合适。就像我说的,我的目标是 4.7 .NET 框架。我在适当版本的 Windows 10(版本 1709 / Creator 版本)上运行。1080p 缩放为 100%。此外,我们没有升级到 WPF 的资源。

回答by Nolonar

I've successfully added DPI support for 2 of my Winforms applications targeting .NET 4.5 and 4.7 respectively.

我已经成功地为我的 2 个分别针对 .NET 4.5 和 4.7 的 Winforms 应用程序添加了 DPI 支持。

In the past, I tried adding support via a manifest file with no luck. Fortunately, I found the following solution:

过去,我尝试通过清单文件添加支持,但没有成功。幸运的是,我找到了以下解决方案:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinformsApp
{
    static class Program
    {
        [DllImport("Shcore.dll")]
        static extern int SetProcessDpiAwareness(int PROCESS_DPI_AWARENESS);

        // According to https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
        private enum DpiAwareness
        {
            None = 0,
            SystemAware = 1,
            PerMonitorAware = 2
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            SetProcessDpiAwareness((int)DpiAwareness.PerMonitorAware);

            Application.Run(new MainForm());
        }
    }
}

The above code is what your Program.cs file should look like. Of course, you'll have to port this to VB, but it should be easy enough to do.

上面的代码就是您的 Program.cs 文件的样子。当然,您必须将其移植到 VB,但这应该很容易做到。

This worked perfectly in Windows 10 without the need for any other modification.

这在 Windows 10 中完美运行,无需任何其他修改。

In one of the two Winforms applications I was rendering strings through the Graphicsclass using pixel coordinates, which caused my strings to be offset. The fix was pretty trivial:

在两个 Winforms 应用程序之一中,我Graphics使用像素坐标通过类渲染字符串,这导致我的字符串偏移。修复非常简单:

private void DrawString(Graphics g, string text, int x, int y)
{
    using (var font = new Font("Arial", 12))
    using (var brush = new SolidBrush(Color.White))
        g.DrawString(text, font, brush, LogicalToDeviceUnits(x), LogicalToDeviceUnits(y));
}

Basically, I had to use Control.LogicalToDeviceUnits(int value)to get the pixel coordinates to scale.

基本上,我必须使用Control.LogicalToDeviceUnits(int value)来缩放像素坐标。

Other than that, I didn't need to touch my code at all.

除此之外,我根本不需要触摸我的代码。

回答by cat_in_hat

In my case, I ran into too many glitches with the recommended approach of setting process DPI awareness: minimum form size won't work correctly, random messing up when moving forms across monitors with different DPI, forms cropped for no apparent reason, font Segoe UI won't scale correctly, anchoring controls within splitter containers makes everything float in the wrong position, etc.

就我而言,我在使用推荐的设置进程 DPI 意识的方法时遇到了太多故障:最小表单大小无法正常工作、在具有不同 DPI 的显示器之间移动表单时随机混乱、无缘无故裁剪表单、字体 Segoe UI 无法正确缩放,拆分器容器中的锚定控件会使所有内容都浮动在错误的位置等。

There's also the issue that icons become smaller and you need to update your code to selectively load higher resolution versions for buttons, ListView, TreeView, and so on.

还有一个问题是图标变小了,您需要更新代码以选择性地为按钮、ListView、TreeView 等加载更高分辨率的版本。

The alternative I ended up using is to use Windows 10's setting to override scaling behavior with "GDI Scaling". This can be declared in the app's manifest.

我最终使用的替代方法是使用 Windows 10 的设置来覆盖带有“GDI 缩放”的缩放行为。这可以在应用程序的清单中声明。

Here's the setting, that you can try it out first and see if it meets your needs:

这是设置,您可以先尝试一下,看看它是否满足您的需求:

enter image description here

在此处输入图片说明

This setting can be set automatically by modifying the app.manifest file in your project and adding the following entry:

可以通过修改项目中的 app.manifest 文件并添加以下条目来自动设置此设置:

<asmv3:application>
  <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2017/WindowsSettings">
    <gdiScaling>true</gdiScaling>
  </asmv3:windowsSettings>
</asmv3:application>

The code may give you an error that "asmv3" is not recognized. To add the asmv3 namespace, modify your app.manifest to include it:

该代码可能会提示您无法识别“asmv3”。要添加 asmv3 命名空间,请修改您的 app.manifest 以包含它:

Before:

前:

<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">

After:

后:

<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">