Windows(取决于字体/缩放/缩放)正在调整我的表单大小。
Windows 没有调整您的表单大小。您的表单配置为自动缩放。这由AutoScaleMode Property 控制。 designer 默认值为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 值也会影响在基于字体的缩放中使用的指标。
我想以编程方式找到表单和控件的原始位置和大小(在设计器中设置。在运行时,这些大小和位置会随着表单的创建而变化。
这可以通过在应用自动缩放之前截取该点来实现。由于您正在处理自动生成的代码(Form.designer.cs 文件的 InitializeComponent 方法),因此没有直接的方法可以做到这一点。正是在这种方法中设置了AutoScaleDimensions 和AutoScaleMode。
当您创建一个新表单时,此方法如下所示。
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 或字体时,才会写入 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 属性设置为 Inherit 或 None。然后修改表单的构造函数代码以反映以下内容:
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 区域中。此外,在设置 AutoScaleDimensions 属性之前先设置 AutoScaleMode 属性也很重要。
另一种解决方案(hack)是将AutoScaleMode 属性设置为Font 或DPI,并依赖Initialize 方法的观察模式。在此方法中,表单的Text 属性始终设置在两个缩放属性之后。这允许使用 TextChanged 事件来指示检索设计时边界的适当时间。
public Form1()
{
EventHandler eh = (s,e) => RecursivelyRecordBounds(this);;
TextChanged += eh;
InitializeComponent();
TextChanged -= eh;
}