C# 使现有的.NET Windows应用程序支持DPI

C# 使现有的.NET Windows应用程序支持DPI,c#,.net,winforms,scaling,dpi,C#,.net,Winforms,Scaling,Dpi,我们有一个现有的windows.net应用程序,它使用所有自定义控件 这些天一切都很好,因为我们只是支持默认的96 dpi决议 现在,我们需要我们的应用程序能够识别dpi。我们到下一站时,一切都乱套了 更高分辨率120或144等 最常见的问题 位图缩放问题及解决方案 文本截止 在阅读了MSDN文档等问题后,我试图 在我的应用程序中徒劳地加入这样的修复(因为使用的所有控件都是 定制的,不支持dpi) 在修改application.manifest以启用dpi感知标志并将AutoScaleMode设

我们有一个现有的windows.net应用程序,它使用所有自定义控件

这些天一切都很好,因为我们只是支持默认的96 dpi决议

现在,我们需要我们的应用程序能够识别dpi。我们到下一站时,一切都乱套了

更高分辨率120或144等

最常见的问题

  • 位图缩放问题及解决方案

  • 文本截止

  • 在阅读了MSDN文档等问题后,我试图

    在我的应用程序中徒劳地加入这样的修复(因为使用的所有控件都是

    定制的,不支持dpi)

    在修改application.manifest以启用dpi感知标志并将AutoScaleMode设置为AutoScaleMode后尝试的操作。主窗体和其他窗体上的dpi将AutoScaleMode用作继承

  • 更改了OnLoad事件中的控件字体
  • Graphics g=this.CreateGraphics(); int dpi=int.Parse(g.DpiX.ToString())

    开关(dpi)
    {
    案例125:
    this.Font=新字体(this.Font.FontFamily,this.Font.Size*125.0f/(float)(g.DpiX));
    
    Debug.WriteLine(因此,我的一个应用程序也遇到了同样的问题。我设法通过两步流程解决了这个问题,不幸的是,这需要大量的重构,但在工作完成后,我成功地让我的应用程序在不同的DPI上自动扩展。下面是如何进行的:

  • 必须使用
    AutoScaleMode=AutoScaleMode.Font
    将所有表单设置为缩放。当我进行一些挖掘时,我发现
    AutoScaleMode.Dpi
    并不像人们期望的那样工作。你还应该选择你的标准Dpi单位。假设它是96,因为这就是你的应用程序最初是以任何方式设计的,然后必须将所有表单设置为使用
    AutoScaleDimensions=new System.Drawing.SizeF(6F,13F)
    。您可以从designer视图中设置这些配置。此外,如果您创建了任何自定义控件,它们都应该设置为使用
    AutoScaleMode=AsutoScaleMode.Inherit
    。有了这两件事,您可以放心.NET将对所有静态组件执行所有缩放操作

  • 问题是,框架会将所有控件保持在正确的大小,只要它们不是动态创建并放置在表单中

  • 所以,如果你做了如下事情:

    var myTextBox = new TextBox();
    myTextBox.Location = new System.Drawing.Point(20, 20);
    myForm.Controls.Add(myTextBox);
    
    var graphics = Graphics.FromHwnd(IntPtr.Zero); // This gets the graphics configuration of the current screen
    var scaleX = graphics.DpiX / 96; // 96 was our standard design DPI, remember?
    var scaleY = graphics.DpiY / 96;
    var myTextBox = new TextBox();
    
    myTextBox.Location = new System.Drawing.Point((int)Math.Round(20 * scaleX), (int)Math.Round(20 * scaleY));
    
    myForm.Controls.Add(myTextBox);
    
    然后,该文本框将被放置在位置(20,20)处无论您的DPI是什么,都会导致它在高DPI监视器上看起来不合适。因此,解决方案是从不使用硬编码像素值,而是使用动态缩放的值,具体取决于您当前的DPI配置。因此,您可能需要编写以下内容:

    var myTextBox = new TextBox();
    myTextBox.Location = new System.Drawing.Point(20, 20);
    myForm.Controls.Add(myTextBox);
    
    var graphics = Graphics.FromHwnd(IntPtr.Zero); // This gets the graphics configuration of the current screen
    var scaleX = graphics.DpiX / 96; // 96 was our standard design DPI, remember?
    var scaleY = graphics.DpiY / 96;
    var myTextBox = new TextBox();
    
    myTextBox.Location = new System.Drawing.Point((int)Math.Round(20 * scaleX), (int)Math.Round(20 * scaleY));
    
    myForm.Controls.Add(myTextBox);
    
    这样,您在屏幕上绘制控件的位置将取决于实际的DPI。而且,如果我可以建议的话,我将实际将缩放功能提取到某种帮助器类中,您可以在其中定义方法来缩放x和y上的值,因此您将有一个标准的缩放机制。请注意u在x和y轴上独立缩放,因为某些屏幕在每个轴上具有不同的像素密度


    无论如何,如果您遵循这两个条件,应用程序的外观应该与它所显示的屏幕无关。

    This
    int dpi=int.Parse(g.DpiX.ToString());
    动摇了我内心的某些东西。关于这个问题,我认为,你们不应该通过开关检查DPI。始终使用公式,公式应该适用于任何DPI。你们可能需要修改布局,只使用自动调整大小的
    标签
    并将它们放在
    表格布局面板
    (以保证哪些控件不会重叠)等。如果在
    PictureBox
    内,位图应该可以。如果您是指自定义控件,请再说一遍-formulas+layouting。如果我在这里听起来很愚蠢,对不起……这里的公式是什么意思?例如,对于图像:
    new\u width=width*scale*old\u dpi/new\u dpi;