dotnet / winforms

Windows Forms is a .NET UI framework for building Windows desktop applications.
MIT License
4.37k stars 966 forks source link

Anchoring a Control at a UserControl #3007

Open harborsiem opened 4 years ago

harborsiem commented 4 years ago

See project TestControls. I have colorized the BackColor of UserControl and ListView different. TestControls.zip

RussKie commented 4 years ago

I can see that you scaling the usercontrol instead of letting it being scaled by the host control. If you comment out or remove these lines, you get the desired effect:

--- a/UserControl1.Designer.cs
+++ b/UserControl1.Designer.cs
            // 
            // UserControl1
            // 
-           this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-           this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.BackColor = System.Drawing.Color.AntiqueWhite;
            this.Controls.Add(this.listView);
weltkante commented 4 years ago

I didn't have a look at the sample yet but if I understand it correctly above lines should only be applied once, when loading the user control, afterwards it should be able to be scaled by the host control.

I think the nominal test of whether its a regression should not be removing the autoscale lines, it should be to add the this.Font = new Font("Microsoft Sans Serif", 8f); line to revert the font change of .NET Core - if with added Font it behaves like Desktop Framework its not a regression.

(Thats not to say that removing this lines is wrong, we should just make sure there is no real regression. I can take a look later today.)

weltkante commented 4 years ago

Can confirm, no regression, setting the font back to the one used in Desktop Framework fixes the problem.

Note that it is not enough to set it only in the UserControl, you have to set it in all .designer.cs files which have AutoScaleMode=Font

Technical background information: AutoScaleMode=Font means the designer records the font size which was used in design time, and when at runtime the font size differs it is supposed to auto-scale the form based on the font size difference. This was a historic attempt to make WinForms resolution independent, before the modern ways of DPI based scaling. Changing the default font in .NET Core triggers this rescaling logic.

When you are porting from Desktop Framework to .NET Core you have to either preserve the font explicitly by adding the corresponding lines in the designer.cs files or you have to change AutoScaleMode=Font to something else in the Desktop Framework before porting to .NET Core.

There is an issue for allowing to set the default font globally to reduce the porting pain

kirsan31 commented 4 years ago

@weltkante

This was a historic attempt to make WinForms resolution independent, before the modern ways of DPI based scaling. Changing the default font in .NET Core triggers this rescaling logic.

When you are porting from Desktop Framework to .NET Core you have to either preserve the font explicitly by adding the corresponding lines in the designer.cs files or you have to change AutoScaleMode=Font to something else in the Desktop Framework before porting to .NET Core.

There only one something else - dpi. You recommend switch to dpi when porting from .net to core? Except Application.SetHighDpiMode I have not found any articles/advises about dpi awareness changes in core :( By the way, do you know, why Application.SetHighDpiMode(); uses HighDpiMode.SystemAware by default?

weltkante commented 4 years ago

You don't have to use designer based DPI scaling, you can also turn auto scaling off if you don't want to bother with it or implement DPI scaling yourself in individual controls (can make sense if you are drawing stuff manually anyways).

Also WinForms has historically been bad at DPI scaling, so most desktop applications probably will have trouble with it. If you want to port without looking at DPI scaling its reasonable to turn auto scaling off while porting and look at it later.

I have not found any articles/advises about dpi awareness changes in core

Thats probably because these changes happened before on Desktop Framework already and are sprinkled around in the normal docs, for example here and here or here, and maybe a few blog posts. Can't find any immediate links to the blog posts, but there have been some when the DPI support was improved with different releases. The general recommendation is to use DPI scaling (thats where the improvement work went into), the designer would just not configure it by default for you yet.

Application.SetHighDpiMode was introduced because previously you had to configure it via app.config (in addition to manifest) and since app.config has been partially deprecated it has been replaced by that method.

SystemAware was decided to be the default because it currently "works best" with the implementation WinForms provides. Per monitor aware or higher needs the framework to be able to change scaling on the fly, implementation isn't considered good enough to make it the default yet.

(I've taken these statements from the issue introducing the Application.SetHighDpiMode function)

RussKie commented 4 years ago

@weltkante thank you :)

@harborsiem could you please confirm whether you have designed it in the new Core Designer (if so, which version of VS)?

@dreddy-work any thoughts on the subject?

harborsiem commented 4 years ago

@RussKie I had the example designed with the Framework Designer (.NET 4.7.2). I had also tested the example with .NET Framework with uncommenting the lines in Form1.cs if (!DesignMode) Font = SystemFonts.MessageBoxFont; This is the DefaultFont in .NET Core. And voila one can see that the sizing and anchoring with the usercontrol is perfect.

kirsan31 commented 4 years ago

@weltkante thank you very match! For now, we have net472 app with DpiAwareness PerMonitorV2 enabled and default AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;. And it's behave not very good, but it's ok. The goal was: try to improve HDPI support when migrating to core, because we need workaround default font in whole app anyway... The most confusing thing in all of this is what to do (if any?) with this 2 lines in all forms, in terms of HDPI improvements:

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;

Even after you post:

You don't have to use designer based DPI scaling,

The general recommendation is to use DPI scaling (thats where the improvement work went into), the designer would just not configure it by default for you yet.

Only manual testing I think?

weltkante commented 4 years ago

The most confusing thing in all of this is what to do (if any?) with this 2 lines in all forms, in terms of HDPI improvements:

This is designer generated code, so you ideally should use the designer to change it. Like I described above you have two options:

The point is that you should be using the designer and not manually editing the .designer.cs file, unless you know exactly what you're doing.

If you prefer manual editing of .designer.cs files you could do it in the Desktop Framework designer a few times and compare a before/after diff. If you recognize patterns you may be able to do manually what the designer does, but it is on your own risk of messing up.

Even after you post: [...] Only manual testing I think?

Not sure what you are asking. Like said in my post disabling WinForms DPI handling (setting to AutoScaleMode=None) can make sense when the DPI handling gets in your way and you want manual handling.

kirsan31 commented 4 years ago

@weltkante It's all clear now - thank you once again.

dreddy-work commented 1 year ago

@Olina-Zhang , can you update current status on this scenario against 8.0?

John-Qiao commented 1 year ago

@dreddy-work we tested the sample project against latest .NET 8.0.100-alpha.1.23067.30 build, it works well on 100% screen, but still repro on the HDPI 300% screen.

Scaled 100% screen: 3007-100

Scaled 300% screen: 3007-300

merriemcgaw commented 1 year ago

@dreddy-work can you assess the priority of this?

weltkante commented 1 year ago

If I reread my analysis of the problem correctly this was an issue with the porting workflow from desktop to core (because the default font changed and the original designer files were set to font scaled), not sure theres anything that can be done at runtime beyond setting the default font back to the old value (I think API for this has been added already). Maybe something can be done in the designer to ease porting desktop controls that are font scaled, but I don't think it has yet been identified what is supposed to be done to "resolve" this issue?