创建DPI感知应用程序

RRR*_*RRR 67 c# dpi dpi-aware

我在C#中有一个表单应用程序.当我更改显示器的DPI时,所有控件都会移动.我使用了代码this.AutoScaleMode = AutoScaleMode.Dpi,但它没有避免这个问题.

有没有人有想法?

Try*_*gve 106

编辑:从.NET 4.7开始,Windows窗体改进了对高DPI的支持.在docs.microsoft.com上阅读更多相关内容它仅适用于Win 10 Creators Update及更高版本,因此根据您的用户群使用它可能不太可行.


困难,但并非不可能.您最好的选择是转到WPF,但这可能不太可行.

我花了很多时间来解决这个问题.以下是一些规则/指南,使其无需FlowLayoutPanel或TableLayoutPanel即可正常工作:

  • 始终在默认的96 DPI(100%)中编辑/设计您的应用程序.如果你在120DPI(125%f.ex)中进行设计,那么当你回到96 DPI后再使用它会变得非常糟糕.
  • 我已成功使用AutoScaleMode.Font,我还没有尝试过AutoScaleMode.DPI.
  • 确保在所有容器(表单,面板,标签页,用户控件等)上使用默认字体大小.8,25像素.最好不要在.Designer.cs文件中为所有容器设置它,以便它使用容器类中的默认字体.
  • 所有容器必须使用相同的AutoScaleMode
  • 确保所有容器都在Designer.cs文件中设置了以下行:

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); // for design in 96 DPI

  • 如果您需要在标签/文本框上设置不同的字体大小等,请按控件设置它们,而不是在容器类上设置字体,因为winforms使用容器字体设置来缩放其内容并使f.ex具有不同字体大小的面板它的包含形式保证会产生问题.如果表单上的表单和所有容器使用相同的字体大小,它可能会工作,但我还没有尝试过.
  • 使用具有更高DPI设置的其他计算机或虚拟Windows安装(VMware,Virtual PC,VirtualBox)来立即测试您的设计.只需从DEV机器上的/ bin/Debug文件夹运行已编译的.exe文件即可.

我保证,如果您遵循这些准则,即使您已经使用特定锚点放置控件而不使用流程板,也可以.我们有一个以这种方式构建的应用程序部署在数百台具有不同DPI设置的计算机上,我们不再有任何抱怨.所有表格/容器/网格/按钮/文本字段等大小都与字体一样正确缩放.图像也可以工作,但它们在高DPI时往往会有一点像素化.

编辑:此链接有很多好的信息,特别是如果您选择使用AutoScaleMode.DPI:链接到相关的stackoverflow问题

  • 我们对您上述建议的实验表明这是一个很好的建议.**自从您在3年前发布以来,您是否已经学习了任何其他指导原则?**我们发现了其他几个......发布在这里:http://stackoverflow.com/questions/22735174/how-to-write-winforms-code-that-auto-scales-to-system-font-and- DPI的设置 (3认同)
  • 我没有尝试使用FlowLayoutPanel,但是在每个表单或usercontrols .Designer.cs文件(由Visual Studio设计器生成的部分类文件)中,您需要设置AutoScaleDimensions和AutoScaleMode.这适用于"正常"形式,您可以使用锚点放置控件,例如.你有一个特定的x和y坐标为它的位置 (2认同)
  • 谢谢,非常有用的帖子.我在一个项目中遇到了这个问题,我必须在其他人之后修复.只需从所有*.Designer.cs文件中删除所有AutoScale*行,现在就可以使用了. (2认同)
  • @MuratfromDaminionSoftware:是的,它有它的警告.在发布时(5年前),高DPI屏幕并不常见,但这种情况发生了很大变化.在更高的DPI中开发的问题在于,所有.Designer生成的代码都变得特定于较高的DPI并且在构建之后返回到较低的DPI使得一切都变得错误.在构建之后向上移动到更高的DPI工作正常. (2认同)

小智 14

我终于找到了屏幕方向和DPI处理问题的解决方案.
微软已经提供了一个解释它的文档,但有一点点缺陷会彻底破坏DPI处理.只需按照下面"为每个方向创建单独的布局代码"下面的文档提供的解决方案 http://msdn.microsoft.com/en-us/library/ms838174.aspx

那么重要部分!在每个末尾的Landscape()和Portrait()方法的代码中添加以下行:

this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
Run Code Online (Sandbox Code Playgroud)

所以,这两种方法的代码就像:

protected void Portrait()
{
   this.SuspendLayout();
   this.crawlTime.Location = new System.Drawing.Point(88, 216);
   this.crawlTime.Size = new System.Drawing.Size(136, 16);
   this.crawlTimeLabel.Location = new System.Drawing.Point(10, 216);
   this.crawlTimeLabel.Size = new System.Drawing.Size(64, 16);
   this.crawlStartTime.Location = new System.Drawing.Point(88, 200);
   this.crawlStartTime.Size = new System.Drawing.Size(136, 16);
   this.crawlStartedLabel.Location = new System.Drawing.Point(10, 200);
   this.crawlStartedLabel.Size = new System.Drawing.Size(64, 16);
   this.light1.Location = new System.Drawing.Point(208, 66);
   this.light1.Size = new System.Drawing.Size(16, 16);
   this.light0.Location = new System.Drawing.Point(192, 66);
   this.light0.Size = new System.Drawing.Size(16, 16);
   this.linkCount.Location = new System.Drawing.Point(88, 182);
   this.linkCount.Size = new System.Drawing.Size(136, 16);
   this.linkCountLabel.Location = new System.Drawing.Point(10, 182);
   this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
   this.currentPageBox.Location = new System.Drawing.Point(10, 84);
   this.currentPageBox.Size = new System.Drawing.Size(214, 90);
   this.currentPageLabel.Location = new System.Drawing.Point(10, 68);
   this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
   this.addressLabel.Location = new System.Drawing.Point(10, 4);
   this.addressLabel.Size = new System.Drawing.Size(214, 16);
   this.noProxyCheck.Location = new System.Drawing.Point(10, 48);
   this.noProxyCheck.Size = new System.Drawing.Size(214, 20);
   this.startButton.Location = new System.Drawing.Point(8, 240);
   this.startButton.Size = new System.Drawing.Size(216, 20);
   this.addressBox.Location = new System.Drawing.Point(10, 24);
   this.addressBox.Size = new System.Drawing.Size(214, 22);

   //note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
   this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
   this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;   //IMPORTANT
   this.ResumeLayout(false);
}

protected void Landscape()
{
   this.SuspendLayout();
   this.crawlTime.Location = new System.Drawing.Point(216, 136);
   this.crawlTime.Size = new System.Drawing.Size(96, 16);
   this.crawlTimeLabel.Location = new System.Drawing.Point(160, 136);
   this.crawlTimeLabel.Size = new System.Drawing.Size(48, 16);
   this.crawlStartTime.Location = new System.Drawing.Point(64, 120);
   this.crawlStartTime.Size = new System.Drawing.Size(248, 16);
   this.crawlStartedLabel.Location = new System.Drawing.Point(8, 120);
   this.crawlStartedLabel.Size = new System.Drawing.Size(48, 16);
   this.light1.Location = new System.Drawing.Point(296, 48);
   this.light1.Size = new System.Drawing.Size(16, 16);
   this.light0.Location = new System.Drawing.Point(280, 48);
   this.light0.Size = new System.Drawing.Size(16, 16);
   this.linkCount.Location = new System.Drawing.Point(80, 136);
   this.linkCount.Size = new System.Drawing.Size(72, 16);
   this.linkCountLabel.Location = new System.Drawing.Point(8, 136);
   this.linkCountLabel.Size = new System.Drawing.Size(64, 16);
   this.currentPageBox.Location = new System.Drawing.Point(10, 64);
   this.currentPageBox.Size = new System.Drawing.Size(302, 48);
   this.currentPageLabel.Location = new System.Drawing.Point(10, 48);
   this.currentPageLabel.Size = new System.Drawing.Size(100, 16);
   this.addressLabel.Location = new System.Drawing.Point(10, 4);
   this.addressLabel.Size = new System.Drawing.Size(50, 16);
   this.noProxyCheck.Location = new System.Drawing.Point(168, 16);
   this.noProxyCheck.Size = new System.Drawing.Size(152, 24);
   this.startButton.Location = new System.Drawing.Point(8, 160);
   this.startButton.Size = new System.Drawing.Size(304, 20);
   this.addressBox.Location = new System.Drawing.Point(10, 20);
   this.addressBox.Size = new System.Drawing.Size(150, 22);

   //note! USING JUST AUTOSCALEMODE WILL NOT SOLVE ISSUE. MUST USE BOTH!
   this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); //IMPORTANT
   this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;   //IMPORTANT
   this.ResumeLayout(false);
}
Run Code Online (Sandbox Code Playgroud)

对我来说就像魅力一样.


bh_*_*th0 9

如何在高dpi设置中修复模糊的Windows窗体

  1. 转到窗体设计器,然后选择您的窗体(通过单击其标题栏)
  2. 按F4打开"属性"窗口,
  3. 然后找到AutoScaleMode属性
  4. 将其从字体(默认)更改为Dpi.

现在,转到Program.cs(或Main方法所在的文件)并将其更改为:

namespace myApplication
{
    static class Program
    {
        [STAThread]
        static void Main()
        {
            // ***this line is added***
            if (Environment.OSVersion.Version.Major >= 6)
                SetProcessDPIAware();

            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }

        // ***also dllimport of that function***
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern bool SetProcessDPIAware();
    }
}
Run Code Online (Sandbox Code Playgroud)

保存并编译.现在你的表格应该再次看起来很脆.


来源:http: //crsouza.com/2015/04/13/how-to-fix-blurry-windows-forms-windows-in-high-dpi-settings/


小智 6

看起来这是 Windows 的问题。去掉这两行就解决了一切。

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
Run Code Online (Sandbox Code Playgroud)

这是我得到解决方案的地方: