WinForms 不同的 DPI 布局

Posted

技术标签:

【中文标题】WinForms 不同的 DPI 布局【英文标题】:WinForms Different DPI Layouts 【发布时间】:2010-12-23 11:34:34 【问题描述】:

不知何故,通过 Visual Studio 和设计器创建的表单和控件能够根据 Windows 的当前 DPI/字体大小自行缩放。我的 UI 的一部分是一个选项卡控件,其中包含根据用户的选择生成的动态页面和标签/输入。创建这些时,它们使用看起来适合 96 DPI 的硬编码尺寸。

.Net 中是否有一种自动方式来获取这些生成的控件并执行与设计器生成的控件相同的大小调整?我想避免自己缩放控件,因为这是不易维护的旧代码。

【问题讨论】:

【参考方案1】:

嗯,通过迭代标签页的 Control 集合并将 Point 和 Size 属性乘以缩放因子,这在技术上很容易做到。但是,一旦您开始考虑 Dock 和 Anchor 属性,这将变得非常棘手。

到目前为止,最简单的方法是让 Form 类缩放机制为您完成这项工作。您需要将控件添加到标签页之前 Load 事件运行。在构造函数中执行此操作。

避免切换 DPI 设置以测试代码的痛苦的快速提示:将其添加到表单构造函数以调用重新缩放逻辑:

protected override void OnLoad(EventArgs e) 
    this.Font = new Font(this.Font.FontFamily, this.Font.Size * 120 / 96);
    base.OnLoad(e);

【讨论】:

@nobugz :假设有多种不同类型的标签页(每种类型都有不同的内部控件):这些是否可以预定义为 UserControls:以获得“表单类缩放机制”的相同好处所以:在运行时:如果用户创建了一个类型为#3 的新标签页:新标签页的控件集合设置为 UserControl3 停靠的新实例“填充”,它当然会调用 UserControl 的“加载”事件:在这种情况下,UserControl 是否也能正常缩放?谢谢, 是的,伸缩是由ContainerControl实现的。和 Form 一样,UserControl 也是从它派生而来的。 @nobuz 谢谢,我从您的回答中学到的信息,以及同样适用于 UserControls 的确认非常有价值!【参考方案2】:

您尝试过AutoScaleMode 属性吗?

【讨论】:

是的,AutoScaleMode 使我的其他控件可以完美缩放,但它似乎不会影响动态控件。我还模仿了设计人员在生成控件时使用的 Suspend/ResumeLayout 和 PerformLayout 调用。【参考方案3】:

我解决了同样的问题,在运行时根据需要创建了控件,方法是执行 Designer.cs 所做的:

void CreateRuntimePanel()

    //instantiate controls here...

    //suspend layouts
    //begin inits

    this.SuspendLayout();

    //set control properties here

    //before adding any control to form's Controls collection, do this
    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

    //add controls to form's Controls collection here

    //resume layouts
    //end inits

    this.ResumeLayout(false);  

【讨论】:

以上是关于WinForms 不同的 DPI 布局的主要内容,如果未能解决你的问题,请参考以下文章

如何编写自动扩展到系统字体和dpi设置的WinForms代码?

TextRenderer:如何像在具有不同 Dpi 的机器上一样测量文本?

WPF 不同DPI下,窗口大小的处理

[转]Easily Add a Ribbon into a WinForms Application

如何强制高 DPI 手机在引导程序中打开 xs 布局

target-densitydpi=device-dpi会使其他ui插件布局变小