繁体   English   中英

C# WinForms 禁用 DPI 缩放

[英]C# WinForms disable DPI scaling

我有一个承载许多图像的 WinForm 应用程序。 当我将应用程序放在 DPI 为 120 的 Win7 机器上时,它完全破坏了表单的外观。 有没有办法禁用我的表单的缩放?

我知道这是不建议的,DPI 应该是无缝的并且由操作系统处理。 但是当涉及到皮肤应用程序时,图像不能很好地缩放。 我没有为所有 DPI 变化创建图像的奢侈,所以请不要建议将其作为答案。

更改AutoScaleMode属性时,您会遇到更大的问题。 增加DPI也会更改系统字体大小。 因此,字体大小必须以1/72英寸的磅数表示。 当DPI增大时,字体必须更大,以得到相同的磅值,并且从相同的距离观看时,文本应保持可读性。

由于控件不再调整大小,因此按钮上的文本不再适合。 解决此问题的一种方法是按比例更改控件上的字体大小。 如果让所有控件继承表单字体,则很容易,只需更改表单的Font属性即可自动更新控件。 明显的缺点是用户将很难阅读文本。 当DPI达到每英寸150点甚至更高时,这特别糟糕,您的UI变成了无法使用的邮票。

是的,需要缩放背景图像以适合较大的控件或窗体。 图像中的像素现在不再一对一映射到监视器的像素。 默认的Graphics.InterpolationMode值在过滤图像方面做得相当不错。 但这取决于图像的种类,结果如何。 一张照片几乎总是可以很好地缩放。 精细的线条和文字则没有。 选择正确的图像对于避免不得不创建单独的图像有很长的路要走。

在显示器开始具有打印机所具有的分辨率之前,这个问题不会消失。 与台式机显示器的600 dpi相比,我们还有很长的路要走。 手机将是第一个。

在自动生成的对Form1构造函数中的InitializeComponent的调用之前添加一行代码为我解决了该问题:

public partial class Form1 : Form
{
    public Form1()
    {
        // Make the GUI ignore the DPI setting
        Font = new Font(Font.Name, 8.25f * 96f / CreateGraphics().DpiX, Font.Style, Font.Unit, Font.GdiCharSet, Font.GdiVerticalFont);
        InitializeComponent();
    }
}

您可以将窗体的AutoScaleMode属性设置为None

创建一个应用程序清单文件(右键单击项目/添加/新项/应用程序文件),然后取消注释此部分:

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

此网站的信誉: https ://www.telerik.com/blogs/winforms-scaling-at-large-dpi-settings-is-it-even-possible-

字体的大小增加了,但 UI 元素的大小保持不变。 如果您查看出了什么问题,您应该能够想到 UI 的某些部分需要放大。 这可以包括:

  • 每个窗口的大小。
  • 任何绝对大小的列的宽度。
  • 任何绝对大小的行的高度。
  • 任何绝对大小的元素的大小。

(基本上它是绝对大小的任何东西。)

您可以使用以下内容检测 DPI 比例因子:

static (float X, float Y)? sMaybeCachedFactors;

public static (float X, float Y) GetDPIFactors(
   this Control me
) {
   if (sMaybeCachedFactors is { } cachedFactors)
      return cachedFactors;

   using var g = me.CreateGraphics();
   sMaybeCachedFactors = cachedFactors = (g.DpiX / 96f, g.DpiY / 96f);

   return cachedFactors;
}

然后,您可以在正确的位置使用这些值来扩展您的 UI。

例如,如果您通常将窗口的大小设置为 800x600:

// instead of 
Size = new Size(800, 600);

// you would do this
var factors = this.GetDPIFactors();
Size = new Size(800 * factors.X, 600 * factors.Y);

此外,您可以使用更具体的东西来表示比例因子,而不是我迄今为止使用的(float, float)元组,然后它可以更容易地应用于缩放事物,使用运算符等。

var factors = this.GetDPIFactors();
Size = factors.GetSize(800, 600); // scaled automatically

// or

Size = new Size(800, 600) * factors; // * operator

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM