0

I have a System.Windows.Forms.UserControl which performs a this.ResumeLayout(false) at the end of the method InitializeComponent.

I would like to know if there is any way or event to handle just before the code for the ResumeLayout is executed.

I need to get the value for the property this.AutoScaleFactor just before ResumeLayout is executed. If that possible? If so, how.

It is so difficult to get around this because the code in InitializeComponent method is automatically generated by Visual Studio and ResumeLayout is being put there automatically as the last líne of the InitializeComponent. So I am also wondering if it is possible to tell Visual Studio to not add ResumeLayout(false) at the end of this method so I can call it manually later outside the InitializeComponent just after I get the scaling factor through this.AutoScaleFactor. For example in the constructor of the UserControl do:

InitializeComponent();
var scaleFactor = this.AutoScaleFactor;
this.ResumeLayout(false);
Willy
  • 9,848
  • 22
  • 141
  • 284
  • 1
    As [mentioned before](https://stackoverflow.com/q/73214117/7444103), the `AutoScaleFactor` is determined by the proportion between `AutoScaleDimensions` and `CurrentAutoScaleDimensions`. You know the `AutoScaleDimensions`, it's the Design-Time time value based on `AutoScaleMode` and the current Font scale. You can read it from the `.Design.cs` file or calculate it yourself. `CurrentAutoScaleDimensions` is set at Run-Time. You can re-calculate this proportion whenever you want to, it's just `SizeF scale = new SizeF([Current].Width / [Original].Width, [Current].Height / [Original].Height);`. – Jimi Aug 03 '22 at 15:54
  • 1
    BTW, you should design at 100% scale and, since your UserControl will become DpiAware, design for this instead of scaling to Font. – Jimi Aug 03 '22 at 15:54
  • @Jimi You say that I can re-calculate this proportion whenever I want through the formula you provided. Okay, the problem is that I do not know how to retrieve [Current] and [Original] from the UserControl. Could you please indicate me how? A code snippet would be highly appreciated. Thanks in advance. – Willy Aug 03 '22 at 15:59
  • 1
    `[Current]` is `CurrentAutoScaleDimensions`, `[Original]` is `AutoScaleDimensions` (set at Design-Time) -- Have you tried to scale to Dpi instead of Font? DpiAwareness can be set in code (you didn't specify the .Net version). Some info about it [here](https://stackoverflow.com/a/50276714/7444103) – Jimi Aug 03 '22 at 16:01
  • @Jimi okay, but the problem is that since ResumeLayout is done from within the auto-generated code (InitializeComponent), if I re-calculate it from the UserControl constructor and after ResumeLayout is executed, then both CurrentAutoScaleDimensions and AutoScaleDimensions match, i mean, are the same, so if you apply your formula then you get scale (1, 1) which is not what I expect because when ResumeLayout is executed, the scaling is applied, and hence that CurrentAutoScaleDimensions and AutoScaleDimensions are the same. – Willy Aug 03 '22 at 16:04
  • 1
    Of course those are the same after the Layout is performed, I've already mentioned that in your previous question. But you know what that value is, since it's set at Design-Time, you just need to read it (or calculated it, it's based on the Font Height and the Em width) – Jimi Aug 03 '22 at 16:06
  • @Jimi so you mean I can re-calculate it even after ResumeLayout has been executed? What value you mean I know because it is set at Design-Time? CurrentAutoScaleDimensions or AutoScaleDimensions. Sorry I a little bit lost. – Willy Aug 03 '22 at 16:10
  • 1
    `CurrentAutoScaleDimensions` is the Run-Time value, `AutoScaleDimensions` is the Design-Time value, based on he Font size and the current Font scale (here comes a problem, since you're not designing at 100% scale, you should have a warning about that). But you can simply read it from the `.Designer.cs` file -- It would be easier to understand what the problem is if you described what practial problem you're trying to solve. When the Layout is performed, all Controls that inherit the Font are scaled accordingly (unless, as mentioned, you set `AutoScaleMode = None` or you scale to Dpi) – Jimi Aug 03 '22 at 16:12
  • @Jimi Okay, thanks a lot, I understand now. The design-time value is always meet and despite it is changed to be the same as CurrentAutoScaleDimensions after scaling (ResumeLayout), I can always hardcoded it, I mean, re-calculate with your formula the scaling factor in wherever and whenever I want using the value in MyUserControl.Designer.cs (within InitializeComponent method). This avoids doing the trick at the constructor: SuspendLayout, InitializeComponent, get scaling factor and then ResumeLayout as provided as answer here in the post. [To be continued on next post] – Willy Aug 03 '22 at 20:33
  • @Jimi The problem doing so is that you are hard-coding it in your formula so if in the future it is changed within InitializeComponent in MyUserControl.Designer.cs then you need to modify also the hard-coded value used for the formula again. Regarding I am not designing at 100%, it's true, my Windows is set to 200% scale. I have tried to modify it to be 100% but again comes back to 200%. I have a Windows 11 RTM virtual machine running on Parallels. – Willy Aug 03 '22 at 20:36
  • @Jimi Also I am having another problem, if in MyUserContorl.Designer.cs I specify AutoScaleDimensions as (6F, 13F) it works, even in other computers with different screen resolutions but if I set AutoScaleDimensions to something different from (6F, 13F), let's say for example (12F, 25F) then it does not work in other computers with different screen resolutions. Do you maybe know why it is happening? – Willy Aug 03 '22 at 20:37
  • 1
    I've mentioned that before. You're scaling to Font (a size of `(6F, 13F)` tells me that you're using - most probably - Microsoft Sans serif with a `8.25pt` size, which scales to `(12F, 25F)` with a x2 multiplier - 200%). This has a number of problem since - this has been also mentioned - your UserControl is going to become DpiAware when added to a WPF app. You should scale to Dpi (your AutoScaleDimensions will become `(192F, 192F)`, i.e `(96F, 96F) x 2` at 200%), design for this using resizable containers and size the UC to its Parent. – Jimi Aug 03 '22 at 21:14
  • 1
    If you then need to scale the Font, you can do that based on the current Screen resolution (its current Dpi), compared to the resolution the UC was designed for (also considering that the WPF app could be moved to a Screen with a different resolution - *resolution* still means Dpi. That's the reason why designing at 100% scale makes it *simpler*). Note that child Controls inherit the Font from the UC container, so if you scale (on your terms) the UC's Font, all Controls will scale accordingly. This is something you have to test (quite a lot, I know) – Jimi Aug 03 '22 at 21:14
  • Besides the notes you can find in the Q&A linked in the first comment, the notes here: [Using SetWindowPos with multiple monitors](https://stackoverflow.com/a/53026765/7444103) may also be useful (you cannot try and ignore the DpiAwareness thing). – Jimi Aug 03 '22 at 21:30
  • Yes, I am using Microsoft Sans serif with a 8.25pt. I have solved the issue about the scale in Windows. I modified a setting in Parallels regarding to virtual machine, by enabling scaling. Afterwards I can change scale to 100% in Windows. After doing that, now Visual Studio Designer adds the AutoScaleDimensions set to (6F, 13F) in the InitializeMethod. – Willy Aug 03 '22 at 22:45

1 Answers1

1

You can just call SuspendLayout before InitializeComponent, then call ResumeLayout afterwards. As noted in Do Control.SuspendLayout and Control.ResumeLayout keep count?, the control keeps count of how many times you call it and does not redo the layout until you call ResumeLayout enough times.

this.SuspendLayout();
InitializeComponent();
var scaleFactor = this.AutoScaleFactor;
this.ResumeLayout(false);
Charlieface
  • 52,284
  • 6
  • 19
  • 43