dotnet / winforms

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

Font autoscaling doesn't function in .NET Core as it does in .NET Framework 4.8. #11214

Open swapso opened 5 months ago

swapso commented 5 months ago

Description

I've just migrated a Winform project from .NET Framework 4.8 to .NET Core 9, following the porting instructions provided in the Windows documentation. However, I've encountered an issue with font autoscaling. When I adjust the font for the entire application, the controls on the form don't scale appropriately.

Reproduction Steps

  1. Create small Multi-windows winform application (an app which can open multiple forms in the same app) based on .NET Framework 4.8 having a single form with basic ui control like labels, buttons, textboxes.
  2. Create a form of changing font of entire application in the application.
  3. Port above .NET 4.8 project to using .NET core with latest version (Also, keep copy of .Net 4.8 version)
  4. Run both project, open a form, observe controls properties before and after changing font size.
  5. For reference, .NET 4.8 uses default 'Microsoft san serif' with 8.25 Small font size and .Net core uses 'Segoe UI' with 9 small font size.

Expected behavior

In a NET Core project, after changing the font, the properties of the controls like SizeX, SizeY, LocationX, and LocationY should be set to the same values as in the NET 4.8 project during events like onLoad, onShown, and FontChanged.

I have attached my application expected screenshot. Correct

Actual behavior

In a NET Core project these properties are not getting set correctly, which ultimately causing winform UI to set weirdly.

I have attached my application actual screenshot. weird

Regression?

No response

Known Workarounds

4 8 code

Above is NET 4.8 code from System.Windows.Forms->Systems->Windows->Forms->Layout->Containers->ContainerControls.cs

and below is the same code from NET Core

Core code

Look at difference, because of base.IsHandleCreated NET Core doesn't allow to take effect of FontChanged. if we remove that base.IsHandleCreated from code and test the application it works fine.

Configuration

.NET version- 4.8 and .NET Core Windows 10 x64 Architecture

Other information

No response

Suchiman commented 5 months ago

This issue should probably be moved to dotnet/winforms. IsHandleCreated was added in this commit: https://github.com/dotnet/winforms/commit/9b77d919753564d3a47799c59ca426686e7daf70

RussKie commented 5 months ago

@swapso I believe what you're seeing is expected and by design due to the change in the default font (documented here). To ease the pain of the migration in .NET 6 we introduced Application.SetDefaultFont API and the application bootstrap (documented here, blogged here). Setting the application default font to ""Microsoft Sans Serif, 8pt" should set your layouts back to the original.

I would also recommend reviewing the list of the breaking changes Windows Forms SDK accepted moving from .NET Framework to .NET.

swapso commented 5 months ago

@RussKie, you're spot on. It only functions correctly when the forms are already open, as IsHandleCreated returns true in that scenario. However, if the form is closed and we modify the font for the application from another part of the application, then open the form again, IsHandleCreated returns false, leading to improper scaling.

swapso commented 5 months ago

Difference between NET 4.8 & NET Core font scaling.pdf

Hi @RussKie @Suchiman To support my statements, I have created two separate applications based on NET Core & NET 4.8. In Above documents I have provided github links to clone the repos and step-by-step workflow to reproduce the same error I am facing.

Please go through it once. You will observe how IsHandleCreated comes false in case TabControl contained controls.

RussKie commented 4 months ago

Thank you @swapso, that's for @dotnet/dotnet-winforms team to investigate.

LeafShi1 commented 4 months ago

This problem can be reproduced by setting a larger font size for the form and making the control layout in the Form more compact. WinFormsApp3.zip

image

swapso commented 4 months ago

https://github.com/dotnet/winforms/pull/11213

@RussKie @LeafShi1

In above pull request I have provided a solution to bypass this IsHandleCreated condition. May I know how to get these changes approved ?

merriemcgaw commented 4 months ago

@swapso thank you for raising this issue. A change in this part of the code is extremely risky and can have a lot of unintended consequences. @LeafShi1 - can your team do a deep dive into a workaround, perhaps enforcing SuspendLayout when handle is created?

swapso commented 4 months ago

@merriemcgaw @LeafShi1 @ricardobossan can you provide me an update on this issue?

LeafShi1 commented 4 months ago

@merriemcgaw @ricardobossan @Tanya-Solyanik The reason for this problem is that PerformAutoScale is not executed, because when the Form object is created, its handle is not created immediately, this is by design.

So the way to fix this problem

  1. As a workaround, force creation of Handle before font change image
  2. Update judgment here so that PerformAutoScalecan be executed. Can we consider the following judgment logic? if (AutoScaleMode != AutoScaleMode.None && (IsHandleCreated || Font != DefaultFont))
merriemcgaw commented 4 months ago

Thanks for the workaround @LeafShi1! @swapso does this solve your issue?

swapso commented 3 months ago

@merriemcgaw I will test the changes and let you know soon

swapso commented 3 months ago

Hi @merriemcgaw , @LeafShi1 @Tanya-Solyanik Previously I was using below document to test the changes. But now its not working, even after copying DLL to shared folder when I run my program, I am not getting modified SDK files in debug. I also enabled in VS under Tools->Options->Environment->Preview Features->Use previews of the .Net Core SDK (Requires restart) setting.

Document: https://github.com/dotnet/winforms/blob/main/docs/debugging.md

am I missing something?

LeafShi1 commented 3 months ago

Hi @merriemcgaw , @LeafShi1 @Tanya-Solyanik Previously I was using below document to test the changes. But now its not working, even after copying DLL to shared folder when I run my program, I am not getting modified SDK files in debug. I also enabled in VS under Tools->Options->Environment->Preview Features->Use previews of the .Net Core SDK (Requires restart) setting.

Document: https://github.com/dotnet/winforms/blob/main/docs/debugging.md

am I missing something?

Is there any error? You can try to upgrade the .net SDK to latest version.

swapso commented 2 months ago

@LeafShi1 There is no specific error, it just don't switch to modified the SDK with above settings. Also, I have already these SDK installed:

  1. Windows 11 SDK (10.0.22621.0)
  2. .NET Framework 4.8 SDK
  3. .NET SDK

image image

LeafShi1 commented 2 months ago

@swapso You may have misunderstood the workaround I provided. You don't need to change the Winform code. You only need to add CreateHandle(); in your Application.

swapso commented 2 months ago

@LeafShi1 oh thanks. I already tried & tested adding CreateHandle(); in my application and it works.

But to close this issue, I guess I need to change in Winform code and then submit a PR for this issue. Isn't it? Or you guys will do it?

swapso commented 2 months ago

@LeafShi1 Sorry for the confusion what I write in earlier comment. The CreateHandle(); worked in my sample application for single form only. When I tried to put it in base form, it just don't work. Also, in my main application even after putting CreateHandle(); for a single form don't work.

LeafShi1 commented 2 months ago

@LeafShi1 Sorry for the confusion what I write in earlier comment. The CreateHandle(); worked in my sample application for single form only. When I tried to put it in base form, it just don't work. Also, in my main application even after putting CreateHandle(); for a single form don't work.

I see. Font settings may be more complicated in real applications. CreateHandle(); can only solve the problem of setting the default font when the Form is initially sized. We will revisit this issue.

Camel-RD commented 1 month ago

There's also an issue with a specific nesting of controls that won't allow auto-scaling for some controls. When a control is placed in a SplitContainer inside a TabControl on its second page, this control isn't included in the auto-scaling until after the second page has been created (selected). TestAutoScaleOnFontChange.zip

swapso commented 4 weeks ago

Hi @LeafShi1

I made the changes you provided in winform code. Built and exported DLL and tested it with my application. it works. Every contols are properly scaled according to font size.

Steps I took:

  1. Set my targetFramwork to 'net9.0-windows'. because i was using .NET 9 preview version. net9.0-windows
  2. Enabled visual studio option in Debug -> Options -> Environment -> Preview features: Use previews of the .NET SDK.
  3. By following guide https://github.com/dotnet/winforms/blob/main/docs/debugging.md updated DLL at appropriate path, so visual studio can reference DLL while building app.

@Camel-RD even tested your application 'TestAutoScaleOnFontChange.zip' , it also work with that.

code changes in winform screenshot attached below. (updated if condition) image

@LeafShi1 Let me know so we can close this issue.

LeafShi1 commented 4 weeks ago

estAutoScaleOnFontChange.zip' , it also work with that.

Thanks for your feedback, we need to discuss the feasibility of this fix and whether it can solve all possible situations.

swapso commented 4 weeks ago

@LeafShi1 if we can move faster, we want these small changes to go live in the next .NET preview version Or get added in the previous version .NET

Let me know how can I help to do it faster.

LeafShi1 commented 3 weeks ago

Let me know how can I help to do it faster.

For issue tracking, please see the comment below PR #11641

swapso commented 4 days ago

@LeafShi1 why PR#11641 is closed? What happened to new infrastructure that Jeremy was planning to rework.