简体   繁体   中英

Winforms control positioning

I need to add controls programmatically to a custom control and position them in a certain layout. I thought it would be easy enough create a replica at design time inside a panel and then use the generated code to build them in another panel at runtime.

The dimensions such as widths, height & size are not working as expected between runtime vs design time. Why is this?

Eg below has 2 design time panels. The panel on the left contains design time controls and the one on the right runtime controls. this.dateTimePicker1.Size = new System.Drawing.Size(219, 26); sets the width = 219

However, at runtime dtp2.Size = new System.Drawing.Size(219, 26); is too long and I have to use dtp1.Width = 150; instead. Why 150 and not 219?

在此输入图像描述

RunTime Control Code:

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

DesignTime Control Code:

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

    }

Your problem is with Autoscaling .

This code:

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

May not imply that this.dateTimePicker1.Size is really 219 x 26. Why? Because of this line here, from .designer.cs:

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

After that line an in-memory scaling is performed. This scaling is executed on all child controls right after this line:

this.groupBox1.PerformLayout();

After that, this.dateTimePicker1.Size will change to something closer to 150 in width. You may also notice that designer code does not match what's displayed in the properties pane when control is selected.

Add something to the form to cause a change in the designer file and save it. This will at cause .designer.cs code to match the screen DPI and you won't see any inconsistencies any more. It seems that your DPI setting is higher than the one used when creating the form - if this is accidental, correct your Windows DPI setting to 96 or 100%.

Once your form designer matches your screen DPI, you will see that all the size and location properties have been changed and that there is a new value set on AutoScaleDimensions , write down this value because this is the dimension that matches your screen DPI.

Now, whenever you want your controls' locations and sizes to respect the screen DPI you have to place your control logic in something like this:

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

This would cause whatever controls placed in between to be scaled to whatever DPI is currently on the screen.

Note that 6F, 13F are values most people have for 96 DPI setting (default 100% zoom in Windows). This is why I asked to write down your value so you can use that instead.

If you still don't find this obnoxious you can also read up this question which has extra info: Creating a DPI-Aware Application .

I forgot to mention something - if you work in a team with source control software, take extra care because whenever you save something in designer it's going to alter every Size and Location to match your own setting (as explained above). 我忘记提及一些事情 - 如果您在拥有源代码控制软件的团队中工作,请格外小心,因为每当您在设计器中保存某些内容时,它将改变每个SizeLocation以匹配您自己的设置(如上所述)。 This shouldn't cause problems but you should be always aware of this.

try changing

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

to

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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