繁体   English   中英

如何从原始设计器设置中获取控件的 position 和大小?

[英]How do I get a control's position and size from the original designer settings?

Windows(取决于字体/缩放/缩放)正在调整我的表单大小。 我想以编程方式找到原始 position 以及表单和控件的大小(在设计器中设置。在运行时,这些大小和位置会随着表单的创建而变化。

Windows(取决于字体/缩放/缩放)正在调整我的表单大小。

Windows 没有调整您的表单大小。 您的表单配置为自动缩放。 这由AutoScaleMode 属性控制。 设计器默认值为System.Windows.Forms.AutoScaleMode.Font (真正的默认值为Inherit )。 WinForm 自动缩放的高级概述可以在文档Current support for automatic scaling中找到。 一个常见的替代值是System.Windows.Forms.AutoScaleMode.DPI 启用自动缩放时,使用AutoScaleDimensions的值计算的缩放因子和使用报告给应用程序的 DPI 在运行时评估的值。 AutoScaleDimensions在设计器生成的代码中设置。

如果应用程序被声明为可识别 DPI,则使用真正的 DPI 值。 如果它不支持 DPI,则 Windows 会告诉该应用程序它正在以 96 dpi 运行。 报告的 DPI 值也会影响在基于字体的缩放中使用的指标。

我想以编程方式找到原始 position 以及表单和控件的大小(在设计器中设置。在运行时,这些大小和位置会随着表单的创建而变化。

这可以通过在应用自动缩放之前截取该点来实现。 由于您正在处理自动生成的代码(Form.designer.cs 文件的 InitializeComponent 方法),因此没有直接的方法可以做到这一点。 正是在此方法中设置了AutoScaleDimensionsAutoScaleMode

当您创建一个新表单时,此方法如下所示。

private void InitializeComponent()
{
    this.components = new System.ComponentModel.Container();
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(800, 450);
    this.Text = "Form1";
}

请注意, AutoScaleDimensions属性尚未在方法中声明; 一旦您对表单进行了一些更改(更改属性或添加控件)并将新信息写入文件,它将被添加。 仅当AutoScaleMode设置为 DPI 或 Font 时才会写入AutoScaleDimensions属性。

以下是更改表单Size的结果。

private void InitializeComponent()
{
    this.SuspendLayout();
    // 
    // Form1
    // 
    this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    this.ClientSize = new System.Drawing.Size(782, 453);
    this.Name = "Form1";
    this.Text = "Form1";
    this.ResumeLayout(false);
}

显示上述内容的目的是向您展示如何在以下建议的解决方案中获取设置AutoScaleDimensions属性的值。

建议的解决方案

在设计器中,将表单的 AutoScaleMode 属性设置为InheritNone 然后修改表单的构造函数代码以反映以下内容:

SizeF scalingFactor;
public Form1()
{
    InitializeComponent();

    SuspendLayout();
    AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
    AutoScaleDimensions = new System.Drawing.SizeF(8.0F, 16.0F);

    // at this point you can obtain the scaling factor that will
    // be applied on ResumeLayout
    scalingFactor = AutoScaleFactor;

    // store the design-time bounds in the control's Tag property
    RecursivelyRecordBounds(this);
    ResumeLayout(true);
}

还要将此方法添加到表单的代码中。

private static void RecursivelyRecordBounds(Control c)
{
    c.Tag = c.Bounds;
    foreach (Control cc in c.Controls)
    {
        cc.Tag = cc.Bounds;
        if (cc.Controls.Count > 0)
        {
            RecursivelyRecordBounds(cc);
        }
    }
}

就本示例而言,每个控件的设计时Bounds都存储在其Tag属性中。 请注意,设置两个自动缩放属性必须包含在 SupendLayout/ResumeLayout 区域中。 此外,在设置AutoScaleMode AutoScaleDimensions也很重要。

另一种解决方案 ( hack ) 是将AutoScaleMode属性设置为 Font 或 DPI,并依赖于Initialize方法的观察模式。 在此方法中,表单的Text属性始终设置在两个缩放属性之后。 这允许使用 TextChanged 事件来指示检索设计时边界的适当时间。

public Form1()
{
    EventHandler eh = (s,e) => RecursivelyRecordBounds(this);;
    TextChanged += eh;
    InitializeComponent();
    TextChanged -= eh;
}

暂无
暂无

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

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