WinForm在运行时改变大小...高DPI相关?

时间:2017-12-20 16:50:54

标签: c# winforms visual-studio-2017

当我在Windows中在视网膜MacBook Pro上的VM中运行我的WinForm应用程序时,表单的大小在运行时缩小,而按钮同时向外移动。这可能导致底部边缘的按钮滑到窗口边缘下方,看不见。由于它们是底部锚定的,因此它们完全无法访问。从Windows原生桌面运行时,应用程序通常表现良好。

只有表单上的字体 DPI AutoScaleMode设置才会出现这种情况。使用继承,表单及其内容非常庞大,但与我设计它们的方式成正比。

我用一个来自模板的新模板WinForm应用程序重现了这一点,除了调整表单大小并按下按钮之外什么都不做。如何在不相对于彼此改变尺寸的情况下扩展应用程序?

这是InitializeComponent()中的designer.cs方法:

  private void InitializeComponent()
  {
        this.sendButton = new System.Windows.Forms.Button();
        this.SuspendLayout();
        // 
        // sendButton
        // 
        this.sendButton.Location = new System.Drawing.Point(60, 856);
        this.sendButton.Margin = new System.Windows.Forms.Padding(4);
        this.sendButton.MinimumSize = new System.Drawing.Size(200, 60);
        this.sendButton.Name = "sendButton";
        this.sendButton.Size = new System.Drawing.Size(200, 62);
        this.sendButton.TabIndex = 1004;
        this.sendButton.Text = "Send";
        this.sendButton.UseVisualStyleBackColor = true;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(12F, 25F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(282, 981);
        this.Controls.Add(this.sendButton);
        this.Name = "Form1";
        this.Text = "Form1";
        this.ResumeLayout(false);

  }

以下是设计师中表单的截图:

Form at design time

在运行时:

Form at runtime

2 个答案:

答案 0 :(得分:6)

这个问题不是由重新缩放问题引起的,而是更为平凡。它是由Form.SetBoundsCore() method引起的,我链接到问题陈述。

您可以使用SystemInformation类查看它,对边界应用约束,以便窗口不能太小并且不能大于监视器。此方法在您的程序中运行两次。第一次是表单的InitializeComponent()方法运行时。请注意,此时表单的大小仍然太大,在重新调整之前它不适合显示器。

也许你闻到了这个bug,它在通过ScaleControl()方法计算新大小之前过早地应用了大小约束。因此,您的设计Size.Height会被显示器的大小限制。 然后缩放窗口以调整DPI差异,产生的高度太小。

通常你可以覆盖像SetBoundsCore()这样的虚方法,但是绕过base.SetBoundsCore()调用是不太实际的。在这种方法中发生了太多的东西,并绕过它可能会导致其他错误。实际的解决方法几乎无法提及。请注意链接代码除非将窗体的WindowState设置为normal,否则它不应用大小约束。因此,您可以通过在设计器中将WindowState设置为Minimized来绕过它。你需要做的就是在Load事件中将它设置为正常,它会在窗口重新调整后触发:

    protected override void OnLoad(EventArgs e) {
        this.WindowState = FormWindowState.Normal;
        base.OnLoad(e);
    }

嘿。扩大规模总是比缩小规模要麻烦得多。

我不会发布更典型的dpiAware代码。在这种情况下类似于:

    protected override void OnLoad(EventArgs e) {
        this.ClientSize = new Size(button1.Width + 2 * button1.Left, button1.Bottom + 10);
        base.OnLoad(e);
    }

因此,只需强制客户区显示控件即可。你可以在底部选择一个控件,在最右边选择一个控件。

答案 1 :(得分:1)

我认为问题是AutoScaleMode。对Form1中的代码进行以下更改:

this.AutoScaleDimensions = new System.Drawing.Size(96, 96);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;

这可以解决您的问题。 SizeF用于Font,对于100%字体大小,其值为(13F, 8F)