c# - Winforms控件定位

标签 c# winforms

我需要以编程方式将控件添加到自定义控件并将它们放置在特定布局中。我认为在设计时在面板内创建一个副本,然后在运行时使用生成的代码在另一个面板中构建它们会很容易。

宽度、高度和大小等尺寸在运行时与设计时之间未按预期工作。这是为什么?

例如,下面有 2 个设计时间面板。左侧面板包含设计时控件,右侧面板包含运行时控件。 this.dateTimePicker1.Size = new System.Drawing.Size(219, 26); 设置宽度 = 219

但是,在运行时 dtp2.Size = new System.Drawing.Size(219, 26); 太长了,我不得不使用 dtp1.Width = 150; 相反。为什么是 150 而不是 219?

enter image description here

运行时控制代码:

    private void BuildControls()
    {

        // 
        // dateTimePicker1
        // 
        DateTimePicker dtp1 = new DateTimePicker();
        dtp1.Location = new System.Drawing.Point(21, 35);
        dtp1.Name = "dateTimePicker1";
        //dtp1.Size = new System.Drawing.Size(219, 26);
        dtp1.Width = 150; //Not 219 as expected?
        dtp1.TabIndex = 1;
        panel2.Controls.Add(dtp1);

        // dateTimePicker2
        // 
        DateTimePicker dtp2 = new DateTimePicker();
        dtp2.Location = new System.Drawing.Point(21, 108);
        dtp2.Name = "dateTimePicker2"; 
        dtp2.Size = new System.Drawing.Size(219, 26); //Copying design time is too wide
        //dtp1.Width = 150;
        dtp2.TabIndex = 2;
        panel2.Controls.Add(dtp2);
    }

设计时控制代码:

    private void InitializeComponent()
    {
        this.panel1 = new System.Windows.Forms.Panel();
        this.label1 = new System.Windows.Forms.Label();
        this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
        this.dateTimePicker2 = new System.Windows.Forms.DateTimePicker();
        this.label2 = new System.Windows.Forms.Label();
        this.panel2 = new System.Windows.Forms.Panel();
        this.panel1.SuspendLayout();
        this.SuspendLayout();
        // 
        // panel1
        // 
        this.panel1.Controls.Add(this.dateTimePicker2);
        this.panel1.Controls.Add(this.label2);
        this.panel1.Controls.Add(this.dateTimePicker1);
        this.panel1.Controls.Add(this.label1);
        this.panel1.Location = new System.Drawing.Point(26, 36);
        this.panel1.Name = "panel1";
        this.panel1.Size = new System.Drawing.Size(288, 514);
        this.panel1.TabIndex = 0;
        // 
        // label1
        // 
        this.label1.AutoSize = true;
        this.label1.Location = new System.Drawing.Point(17, 21);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(87, 20);
        this.label1.TabIndex = 0;
        this.label1.Text = "Start Date:";
        // 
        // dateTimePicker1
        // 
        this.dateTimePicker1.Location = new System.Drawing.Point(21, 44);
        this.dateTimePicker1.Name = "dateTimePicker1";
        this.dateTimePicker1.Size = new System.Drawing.Size(219, 26);
        this.dateTimePicker1.TabIndex = 1;
        // 
        // dateTimePicker2
        // 
        this.dateTimePicker2.Location = new System.Drawing.Point(21, 108);
        this.dateTimePicker2.Name = "dateTimePicker2";
        this.dateTimePicker2.Size = new System.Drawing.Size(219, 26);
        this.dateTimePicker2.TabIndex = 3;
        // 
        // label2
        // 
        this.label2.AutoSize = true;
        this.label2.Location = new System.Drawing.Point(17, 85);
        this.label2.Name = "label2";
        this.label2.Size = new System.Drawing.Size(81, 20);
        this.label2.TabIndex = 2;
        this.label2.Text = "End Date:";
        // 
        // panel2
        // 
        this.panel2.Location = new System.Drawing.Point(450, 260);
        this.panel2.Name = "panel2";
        this.panel2.Size = new System.Drawing.Size(288, 290);
        this.panel2.TabIndex = 1;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(850, 710);
        this.Controls.Add(this.panel2);
        this.Controls.Add(this.panel1);
        this.Name = "Form1";
        this.Text = "Form1";
        this.panel1.ResumeLayout(false);
        this.panel1.PerformLayout();
        this.ResumeLayout(false);

    }

最佳答案

你的问题是 Autoscaling .

这段代码:

this.dateTimePicker1.Size = new System.Drawing.Size(219, 26);

可能并不意味着 this.dateTimePicker1.Size 确实是 219 x 26。为什么?由于此处的这一行,来自 .designer.cs:

this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);

在该行之后执行内存缩放。在此行之后的所有子控件上执行此缩放:

this.groupBox1.PerformLayout();

之后,this.dateTimePicker1.Size 的宽度将变为接近 150。您可能还会注意到设计器代码与选择控件时属性 Pane 中显示的内容不匹配。

解决方案,第 1 部分

向表单添加一些内容以导致设计器文件发生更改并保存。这将导致 .designer.cs 代码与屏幕 DPI 匹配,您将不会再看到任何不一致。您的 DPI 设置似乎高于创建表单时使用的设置 - 如果这是意外,请将 Windows DPI 设置更正为 96 或 100%。

解决方案,第 2 部分

一旦您的表单设计器匹配您的屏幕 DPI,您将看到所有大小和位置属性都已更改并且在 AutoScaleDimensions 上设置了一个新值,记下这个值,因为这是与您的屏幕 DPI 匹配的尺寸。

现在,只要您希望控件的位置和大小符合屏幕 DPI,就必须将您的控件逻辑放在这样的地方:

// Your referential DPI setting (96DPI in this case)
this.AutoScaleDimensions = new SizeF(6F, 13F); 

// TODO: Place your code here

// Setting of your users
this.AutoScaleDimensions = this.CurrentAutoscaleDimensions; 

这会导致放置在两者之间的任何控件缩放到屏幕上当前的任何 DPI。

请注意,6F、13F 是大多数人对 96 DPI 设置(Windows 中默认 100% 缩放)的值。这就是为什么我要求写下你的值(value),以便你可以使用它。

如果你仍然不觉得这个令人讨厌,你也可以阅读这个有额外信息的问题:Creating a DPI-Aware Application .

重要提示 我忘了提一件事 - 如果你在一个使用源代码控制软件的团队中工作,要格外小心,因为每当你在设计器中保存一些东西时,它都会改变每个 SizeLocation 到匹配您自己的设置(如上所述)。这应该不会造成问题,但您应该始终意识到这一点。

关于c# - Winforms控件定位,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29063889/

相关文章:

c# - 在 Windows 应用程序中显示结果

c# - WinForms 中的多色线性渐变

c# - 错误 RG1000 : Unknown build error

c# - 如何从代码隐藏的更新面板中找到客户端元素?

C# listView 闪烁/替代颜色

c# - ASP.NET 的图表控件

c# - 如何从按钮触发 DropDownClosed 事件

c# - 自适应Windows移动应用程序

c# - 如何从 SQL Server 加载图像到图片框?

c# - 如何解决 "The operation has timed out"错误