Skip to content

Fix 11214 by removing IsHandleCreated in OnFontChanged #11641

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

LeafShi1
Copy link
Member

@LeafShi1 LeafShi1 commented Jul 9, 2024

Fixes #11214, #12851

Root Cause

  • The reason for this problem is that PerformAutoScale is not executed, because when the Form object is created, its handle is not created immediately, and we have added a check in our code that the handle must be created before scaling.

Proposed changes

-Add a check on the default font setting in the OnFontChanged function of ContainerControls.cs to ensure that PerformAutoScale is executed smoothly

Customer Impact

  • When the font for the entire application was adjusted, the controls on the form can be scaled appropriately

Risk

  • Minimal

Screenshots

Before

When I adjust the font for the entire application, the controls on the form don't scale appropriately
image

After

The controls on the form can be scaled appropriately after adjust the font for the entire application
image

Test methodology

  • Manually

Test environment(s)

  • .net 9.0.0-preview.7.24355.8
Microsoft Reviewers: Open in CodeFlow

@LeafShi1 LeafShi1 requested a review from a team as a code owner July 9, 2024 09:14
Copy link

codecov bot commented Jul 9, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 75.06831%. Comparing base (10f120d) to head (8af286b).
Report is 235 commits behind head on main.

Additional details and impacted files
@@                 Coverage Diff                 @@
##                main      #11641         +/-   ##
===================================================
+ Coverage   74.51776%   75.06831%   +0.55055%     
===================================================
  Files           3040        3059         +19     
  Lines         629560      632003       +2443     
  Branches       46839       46782         -57     
===================================================
+ Hits          469134      474434       +5300     
+ Misses        157058      154190       -2868     
- Partials        3368        3379         +11     
Flag Coverage Δ
Debug 75.06831% <100.00000%> (+0.55055%) ⬆️
integration 17.93212% <100.00000%> (+0.04159%) ⬆️
production 48.22199% <100.00000%> (+0.80597%) ⬆️
test 97.01631% <ø> (+0.06416%) ⬆️
unit 45.25976% <100.00000%> (+0.71726%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

@LeafShi1 LeafShi1 added the waiting-review This item is waiting on review by one or more members of team label Jul 10, 2024
@Tanya-Solyanik Tanya-Solyanik changed the title Fix 11214 by adding font judgement before executing PerformAutoScale Fix 11214 by adding a default font check before executing PerformAutoScale Jul 10, 2024
@Tanya-Solyanik
Copy link
Contributor

I'm not sure that this fix addresses all possible cases. Fundamentally, we are missing information about what font/DPI the controls are scaled for right now. This fix assumes that the application was designed for the DefaultFont and that the current sizes are still set to the "initial" sizes. The former assumption is reasonable, the latter is not necessarily true. Maybe the application had been resized a couple of times and the current sizes are not appropriate for the default font anymore. Previous layout design relied on the AutoScaling ratios to maintain the current state as related to the original designed sizes. We would need to either revive that logic or to implement an extention on it. I suggest we revisit this bug in NET10

@LeafShi1 LeafShi1 marked this pull request as draft July 15, 2024 01:47
@dotnet-policy-service dotnet-policy-service bot added the draft draft PR label Jul 15, 2024
@Tanya-Solyanik
Copy link
Contributor

@LeafShi1 - let's revisit this change in NET10

@Tanya-Solyanik Tanya-Solyanik removed the waiting-review This item is waiting on review by one or more members of team label Jul 18, 2024
@lonitra lonitra changed the base branch from main to feature/10.0 July 23, 2024 00:55
@lonitra lonitra changed the base branch from feature/10.0 to main August 15, 2024 00:59
@LeafShi1
Copy link
Member Author

I'm not sure that this fix addresses all possible cases. Fundamentally, we are missing information about what font/DPI the controls are scaled for right now. This fix assumes that the application was designed for the DefaultFont and that the current sizes are still set to the "initial" sizes. The former assumption is reasonable, the latter is not necessarily true. Maybe the application had been resized a couple of times and the current sizes are not appropriate for the default font anymore. Previous layout design relied on the AutoScaling ratios to maintain the current state as related to the original designed sizes. We would need to either revive that logic or to implement an extention on it. I suggest we revisit this bug in NET10

@Tanya-Solyanik According to customer feedback, this fix can solve their problem.
This fix assumes that the font is changed before the handle is created. Once the handle is created, the scaling will be executed according to the original logic.

I tried to change the font several times, setting three different fonts in Form.cs and Form.Designer.cs, and the scaling results were normal.

But there is a question, should we scale the font before the handle is created?

@Tanya-Solyanik
Copy link
Contributor

But there is a question, should we scale the font before the handle is created?

We don't have this information at the Handle creation time. In some cases the requested size will be already scaled by the user app and in some it would be the default size. We have Scaling required properties for control sizes, but not for fonts.

@LeafShi1
Copy link
Member Author

But there is a question, should we scale the font before the handle is created?

We don't have this information at the Handle creation time. In some cases the requested size will be already scaled by the user app and in some it would be the default size. We have Scaling required properties for control sizes, but not for fonts.

Whether the form/control automatically scales should not be linked to the handle

I did the following experiment

  • When I set the font for the Form in winform.designer.cs, the form will scale according to the set font size. At this time, the handle of the form has not been created

The call stack it executes is as follows (Run OnFontChanged first and then run PerformAutoScale):

******OnFontChanged*****
   at System.Windows.Forms.ContainerControl.OnFontChanged(EventArgs e)
   at System.Windows.Forms.Form.OnFontChanged(EventArgs e)
   at System.Windows.Forms.Control.set_Font(Font value)
   at ScratchProject.Form1.InitializeComponent()
   at ScratchProject.Form1..ctor()
   at ScratchProject.Program.Main()
*******PerformAutoScale******
   at System.Windows.Forms.ContainerControl.PerformAutoScale(Boolean includedBounds, Boolean excludedBounds, Boolean causedByFontChanged)
   at System.Windows.Forms.ContainerControl.PerformNeededAutoScaleOnLayout()
   at System.Windows.Forms.ContainerControl.OnLayoutResuming(Boolean performLayout)
   at System.Windows.Forms.Control.ResumeLayout(Boolean performLayout)
   at ScratchProject.Form1.InitializeComponent()
   at ScratchProject.Form1..ctor()
   at ScratchProject.Program.Main()
  • When I set the font after InitializeComponent(), the page layout has been determined. At this time, the judgment (IsHandle created) is added, resulting in only the font being changed, and the Form is not scaled

The call stack it executes is as follows (Run PerformAutoScale first and then OnFontChanged):

******PerformAutoScale*******
   at System.Windows.Forms.ContainerControl.PerformAutoScale(Boolean includedBounds, Boolean excludedBounds, Boolean causedByFontChanged)
   at System.Windows.Forms.ContainerControl.PerformNeededAutoScaleOnLayout()
   at System.Windows.Forms.ContainerControl.OnLayoutResuming(Boolean performLayout)
   at System.Windows.Forms.Control.ResumeLayout(Boolean performLayout)
   at ScratchProject.Form1.InitializeComponent()
   at ScratchProject.Form1..ctor()
******OnFontChanged*****
   at System.Windows.Forms.ContainerControl.OnFontChanged(EventArgs e)
   at System.Windows.Forms.Form.OnFontChanged(EventArgs e)
   at System.Windows.Forms.Control.set_Font(Font value)
   at ScratchProject.Form1..ctor()
   at ScratchProject.Program.Main()
   at ScratchProject.Program.Main()

So whether the form automatically scales should not be linked to the handle.
It is indeed inappropriate to add the Font != DefaultFont judgment. As you said, the font may have been changed many times, so delete IsHandleCreated here should be the right solution

What do you think?

@Tanya-Solyanik
Copy link
Contributor

Whether the form/control automatically scales should not be linked to the handle

I'm concerned about scaling for the DPI. At the runtime, the form should be scaled according to the DPI of the screen it's created on from the DPI it was designed on. I.e. if the design time DPI scaling is 100%, but the runtime DPI scaling is 200%, form size should be doubled. If the Form uses AutoScaleMode.Dpi, then font should be rescaled. However, we don't always know what on what screen the control is displayed and we might have to scale font after handle is created, when we know the current screen DPI. And we don't know if the default font had been scaled. It is more efficient to scale the default font and have it applied to all controls in the application than to scale font on each container control.

Jeremy is planning to rework the default font handling. So fix for this issue will depend on the new infrastructure that he will put in. Could you please wait with this this change until that work is done?

@LeafShi1
Copy link
Member Author

Jeremy is planning to rework the default font handling. So fix for this issue will depend on the new infrastructure that he will put in. Could you please wait with this change until that work is done?

OK, I will wait for the new infrastructure

@LeafShi1 LeafShi1 closed this Sep 4, 2024
@github-actions github-actions bot locked and limited conversation to collaborators Oct 6, 2024
@JeremyKuhne JeremyKuhne reopened this Jan 6, 2025
@JeremyKuhne
Copy link
Member

Redoing layout is not something we're going to get to for a while. We should look at a targeted fix for .NET 10 here, even if it is behind a compat switch.

@LeafShi1
Copy link
Member Author

LeafShi1 commented Jan 7, 2025

Redoing layout is not something we're going to get to for a while. We should look at a targeted fix for .NET 10 here, even if it is behind a compat switch.

@JeremyKuhne Do you mean add an AppContext switch for it?

@JeremyKuhne
Copy link
Member

Redoing layout is not something we're going to get to for a while. We should look at a targeted fix for .NET 10 here, even if it is behind a compat switch.

@JeremyKuhne Do you mean add an AppContext switch for it?

If the change is risky, yes.

You're undoing #5557, which is concerning. Presuming doing this would break the other fixes. Whatever we do here it would be good to know how this impacts the bugs fixed by that change.

@LeafShi1 LeafShi1 changed the title Fix 11214 by adding a default font check before executing PerformAutoScale Fix 11214 by removing IsHandleCreated in OnFontChanged Jun 3, 2025
@LeafShi1 LeafShi1 force-pushed the Issue_11214_Fix_Update_judgment_for_PerformAutoScale branch from b72925c to 2c26f66 Compare June 4, 2025 06:13
@LeafShi1 LeafShi1 force-pushed the Issue_11214_Fix_Update_judgment_for_PerformAutoScale branch from 2c26f66 to a828b34 Compare June 4, 2025 06:24
@LeafShi1 LeafShi1 marked this pull request as ready for review June 4, 2025 06:25
@LeafShi1 LeafShi1 requested a review from KlausLoeffelmann June 4, 2025 06:25
@LeafShi1
Copy link
Member Author

LeafShi1 commented Jun 4, 2025

You're undoing #5557, which is concerning. Presuming doing this would break the other fixes. Whatever we do here it would be good to know how this impacts the bugs fixed by that change.

This only undoes the changes to ContainerControl in #5557. This undo does not affect the original fix. The test team has verified that the original issues are still fixed.

@JeremyKuhne @KlausLoeffelmann No other impacts have been found so far, should we stick with the original fix and add a switch here or revert the original change?

@dotnet-policy-service dotnet-policy-service bot removed the draft draft PR label Jun 4, 2025
@KlausLoeffelmann
Copy link
Member

I have a general problem with the Layout scaling, as a series of "fixes" we did in the past opened up different issues.

What I would like to do, is before we address this, come up with a specific HighDPI Layout Test App, which we should use in some exploratory settings, and then go from there, to investigate some status-quo first.

The question I have is:
Do we already have something like this?
And if yes, can someone point me to it, so I can test and play with it myself? 😸

@Olina-Zhang: Do you have a test scenario, which would basically run on a physical machine (not a VM) and include the following tests. If not, could you schedule some time, and have someone do the following steps and document the respective results via screenshots?

  • Set the Resolution of the physical machine as high as possible, and set the scaling to 250%

  • Important: Log-off and Log-on again (no reboot necessary).

  • Make sure, you have Visual Studio 2017 and Visual Studio 2022 installed on that machine.

  • Create a new Solution in Visual Studio 2017, Framework 4.6.x

  • Create a Form. Remember the size of the Form, because for the next scenarios, the Forms should all roughly have the same size. This is important!

  • Set the Forms Text, so it reflects what VS Versions and Framework Version it used (for example "Visual Studio 2017, NetFX 4.6.1". Remember to do that for all the other forms to come.

  • Add a GroupBox, almost full Form's width but only half Form's height, and anchor left, top, right side.

  • Add another GroupBox below that GroupBox, again almost full Form's width, half Form's height, anchored left, top, right and bottom.

  • Add a series of Label/TextBox combinations to the first GroupBox like (First name: [ ]). Make sure, the TextBoxes reach almost the right side of the GroupBox, and are anchored left, top, right. Make sure the TextBoxes are aligned with their labels, and they are aligned with the left sides of the other TextBoxes.

  • Do the same for 2nd GroupBox, but use a TableLayoutPanel to hold the Label/TextBox combinations. Use 40%/60% for the LayoutPanel Columns and AutoHeight for the rows. Make sure, the Margin of the Controls inside of TableLayoutControl are all 5 pixels to each side.

  • Add or edit the app.config file of the Framework project to include the switch to HighDPI SystemAware. Note: This does not count for the .NET 10 version!

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>
    <System.Windows.Forms.ApplicationConfigurationSection>
        <add key="DpiAwareness" value="SystemAware" />
        <add key="EnableWindowsFormsHighDpiAutoResizing" value="true" />
    </System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
  • Now Create a new Solution in Visual Studio 2022. Add a Framework 4.8.X WinForms Project.

  • Repeat the steps, but do NOT copy any things over from 2017, but please create everything manually again with the Designer. Make sure, that the main Form is roughly the same size in Pixels as the Form from the first scenario.

  • Now, add a .NET 10 WinForms project to the Solution.

  • Repeat the steps YET again, and again, do it only with the Designer. Again, make sure, the Form is roughly the same size, and do not copy anything over.

Now.
When you've created all those apps and they are compiling, start them all at the same time, and compare them on the screen. Make individual screenshots, and make one screenshot, which shows all three of them at the same time.

Next: Close all the running Apps and all Visual Studio Instances.

Set the Scaling of the machine back to 100%, but if possible do NOT change the resolution.

Restart the machine

Start VS 2017 and VS 2022, and open all the Forms in the Designer and make screenshots of the Form.

IMPORTANT: Do NOT change the Form or its content, also do not resize the Forms. Just open them and make the Screenshots. You can collapse tool Windows of VS which might be in the way, to get a better view of the Form.

Now, run all the Apps again, and make individual screenshots and one screenshot showing all of them.

Provide all the Screenshots as the test results.

@merriemcgaw, @Olina-Zhang, @LeafShi1 FYI.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Font autoscaling doesn't function in .NET Core as it does in .NET Framework 4.8.
4 participants