【问题标题】:Winforms control positioningWinforms控制定位
【发布时间】:2015-03-15 17:32:33
【问题描述】:

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

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

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

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

运行时控制代码:

    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);

    }

【问题讨论】:

  • 您的原始表单是在一台以 144 dpi(显示小程序中为 150%)运行的机器上创建的。但是您的程序不是dpiAware 或在 96 dpi 机器上运行,因此您使用的尺寸太大了 150%。

标签: c# winforms


【解决方案1】:

您的问题在于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 的宽度。 You may also notice that designer code does not match what's displayed in the properties pane when control is selected.

解决方案,第 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% 缩放)。这就是为什么我要求写下你的价值,以便你可以使用它。

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

重要提示 我忘了提一件事——如果您在一个使用源代码控制软件的团队中工作,请格外小心,因为每当您在设计器中保存某些内容时,它都会更改每个 SizeLocation 以匹配您自己的设置(如上所述)。这应该不会导致问题,但您应该始终注意这一点。

【讨论】:

  • 解决方案,第 2 部分不起作用。特别是,设置AutoScaleDimensions 似乎没有效果,除非你先调用SuspendLayout。看起来正确的操作是:SuspendLayout,将AutoScaleDimensions 设置为设计时尺寸,编辑控件位置/大小,然后ResumeLayout
【解决方案2】:

尝试改变

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 2012-08-29
    相关资源
    最近更新 更多