Skip to content

Auto scale explicitly specified font as per the Settings display text scale. - #6580

Closed
kirsan31 wants to merge 1 commit into
dotnet:mainfrom
kirsan31:FontAutoScale
Closed

Auto scale explicitly specified font as per the Settings display text scale.#6580
kirsan31 wants to merge 1 commit into
dotnet:mainfrom
kirsan31:FontAutoScale

Conversation

@kirsan31

@kirsan31 kirsan31 commented Jan 30, 2022

Copy link
Copy Markdown
Contributor

This is a draft implementation of auto scaling explicitly specified control font as per the Settings display text scale. As already done with app default font.

Fixes #3263 implicitly.

Proposed changes

  • Add public enumeration FontAutoScale:
/// <summary>
///  Specifies the font auto scaling mode used by a control.
/// </summary>
public enum FontAutoScale
{
    /// <summary>
    ///  Scale only if control using system font.
    /// </summary>
    SystemOnly,

    /// <summary>
    ///  Scale if control using system or explicitly specified font.
    /// </summary>
    SystemAndExplicit,

    /// <summary>
    ///  Font scale according to their parent's scaling mode.
    ///  If there is no parent, this behaves as if <see cref="FontAutoScale.SystemOnly"/> were set.
    /// </summary>
    Inherit
}
  • Add public property FontAutoScale to Control class:
/// <summary>
///  Determines the font auto scaling mode of this control.
/// </summary>
public FontAutoScale FontAutoScale { get; set; }
  • Add public property ExplicitFont to Control class. Not required, but probably desirable:
/// <summary>
/// Gets the Font that was explicitly set on control by the application. null if the font was not explicitly set.
/// </summary>
public Font ExplicitFont { get; }

Customer Impact

Customers will be able to use custom fonts without losing the ability to scale using the system font:
image

Regression?

  • No

Risk

  • Risk of regression is low because we leave the old default behavior (only those controls whose font is not explicitly set are scaled).
  • Risk of bugs in new functionality - probably above average.

Screenshots

CLICK ME

Before (150% text size)

.Net6 SystemAware and AutoScaleMode.Font
old_150

After (150% text size)

All explicitly specified fonts are specially made different from the system - italic or bold, controls with system font are marked with text: system font. All FontAutoScale modes also displayed on controls.
.Net7 SystemAware and AutoScaleMode.Font
new_150_2

Before / After gif (125% text size)

.Net7 SystemAware and AutoScaleMode.Font
125

.Net7 SystemAware and AutoScaleMode.Dpi
125_dpi

Before / After video (125% text size and DPI 125 -> 100%)

.Net7 PerMonitorV2 and AutoScaleMode.Font - all work fine until we switch DPI on the fly (and than change FontAutoScale) - need to investigate...

PMV2.mp4

Test methodology

Manual. Testing app (with binary's for simplicity):
FontScale.zip

To do.

Accessibility testing

Not necessary - correct me if I'm wrong.

To do

  • General assessment - is such functionality needed?
  • Evaluation of whether I correctly understood everything about HDPI in WinForms.
  • PerMonitorV2 - everything breaks after we switch DPI on the fly - need to investigate...
  • Discuss what to do with complex (which may have several different fonts) controls such as DataGridView, ListView... Without additional implementation in each of them, scaling will work only if one font is specified for the entire control.
  • Properties, enums, methods naming and descriptions.
  • Mixed mode DpiAwarenessModes (thread level DpiAwareness in the application).
  • Testing.
Microsoft Reviewers: Open in CodeFlow
@ghost ghost assigned kirsan31 Jan 30, 2022
@ghost ghost added the draft draft PR label Jan 31, 2022
@kirsan31

kirsan31 commented Feb 4, 2022

Copy link
Copy Markdown
Contributor Author

@dreddy-work can you briefly look into this? Dose it fit with your understanding of HDPI in WinForms and https://github.com/dotnet/winforms/projects/4?
I need to know is it worth to continue.
Thanks.

@dreddy-work

Copy link
Copy Markdown
Member

@kirsan31, thank you for bringing this up. We eventually looking to add this support in WinForms. We haven't discussed this feature in length yet so, cannot comment on the supported modes or if we go with just one state here (either scale or don't). But this proposal helps in right direction.

Majority of this work involves validating on various combinations of the application scaling. I should be able to take a deeper look next week. Meanwhile, can you explore following combinations with your prototype to capture possible challenges?

  1. Combinations of DpiAwarenessMode and AutoscaleMode? (Possibly on a dual monitor setup especially, when validating for PermonitorV2 mode)
  2. Combinations for Mixed AutoscaleMode ( i.e Child containers differ from parent Form)
  3. Combinations of Explicit Font set on some of the control and for others its, default?
  4. This low priority - Mixed mode DpiAwarenessModes (We support thread level DpiAwareness in the application)

Also, wherever possible, please add gif of the operation instead of screenshot, that helps understand complete context of the issue being reported.

@dreddy-work dreddy-work added the api-suggestion (1) Early API idea and discussion, it is NOT ready for implementation label Feb 4, 2022
@kirsan31

kirsan31 commented Feb 4, 2022

Copy link
Copy Markdown
Contributor Author

@dreddy-work thanks for the response!

  1. Combinations of DpiAwarenessMode and AutoscaleMode? (Possibly on a dual monitor setup especially, when validating for PermonitorV2 mode)

All of my tests was with SystemAware and AutoScaleMode.Font. Is PerMonitorV2 ready for testing? I'm afraid that at this moment it will be difficult to understand whose bug is PerMonitorV2 or FontAutoScale :) Also, I haven't 2 monitors :( But I will try any way...

  1. Combinations for Mixed AutoscaleMode ( i.e Child containers differ from parent Form)
  2. Combinations of Explicit Font set on some of the control and for others its, default?

Already done in test app above - present on screenshot. All explicitly specified fonts are specially made different from the system - italic or bold, controls with system font are marked with text: system font. All FontAutoScale modes also displayed on controls.

  1. This low priority - Mixed mode DpiAwarenessModes (We support thread level DpiAwareness in the application)

Wow didn't even think about that - will have to check...

Also, wherever possible, please add gif of the operation instead of screenshot, that helps understand complete context of the issue being reported.

I always trying to record a video for issue/repro. But in this case (SystemAware of course) I couldn't think of anything else to show besides the final result 🤷‍♂️

@dreddy-work

Copy link
Copy Markdown
Member

Is PerMonitorV2 ready for testing? I'm afraid that at this moment it will be difficult to understand whose bug is PerMonitorV2 or FontAutoScale :)

I agree the PMv2 is not complete but that shouldn't block to find if bug is a result of this change. We can compare with base (before changes) here.

Already done in test app above - present on screenshot.

One thing to include here ( if not already) is AutoscaleMode.DPi. Some common controls (ex : label) are always Font scaled no matter what the AutoscaleMode is while other depend on it.

I always trying to record a video for issue/repro. But in this case (SystemAware of course) I couldn't think of anything else to show besides the final result

Sure. It was a reminder only when you find an interesting issue to report. If everything as expected, screenshots are good enough.

@kirsan31

kirsan31 commented Feb 5, 2022

Copy link
Copy Markdown
Contributor Author

@dreddy-work I have updated 1 post with new testing app and testing results. With PermonitorV2 all seems fine, until we change DPI on the fly, after that in static with FontAutoScale all also seems ok, but changing FontAutoScale mode will behave wrong :(

@dreddy-work

Copy link
Copy Markdown
Member

PerMonitorV2 - everything breaks after we switch DPI on the fly - need to investigate...

On the fly Dpi (changing Dpi while app is running) may need OS support (to raise Dpi changed messages). I would focus on PermonV2 mode excluding on the fly Dpi change for now.

@dreddy-work

Copy link
Copy Markdown
Member

Btw, i am curious what is going wrong in your prototype. please share/post the gif. :) (We can always edit and remove if become irrelevant)

@kirsan31

kirsan31 commented Feb 6, 2022

Copy link
Copy Markdown
Contributor Author

@dreddy-work

Btw, i am curious what is going wrong in your prototype. please share/post the gif. :) (We can always edit and remove if become irrelevant)

All of them already in 1 post, under CLICK ME button. PermonV2 in the last video.

image

--- UPD ---

I spent some time on PermonitorV2 behavior and ran into a lot of problems...

  1. Main problem is that after PermonitorV2 switch all fonts are total mess. The video below is .Net6 (.Net7 the same but I recorded .Net6 to explicitly exclude my bugs). label1 using system font and label3 explicit font. Radio button click here do nothing - simple break point trigger:
PMV2_fb.mp4
  1. A common problem (not PermonitorV2 only) - when we use both DPI scale and SysFont scale font sizes behave differently then when these techniques are used alone:

DPI scaling only - fonts not increasing at all:

image

Font scaling only - fonts increasing by 1.25:

image

DPI scaling + Font scaling - fonts increasing by more then 1.25:

image

2.1 Then I decided to check how the default app font is scaled (should be exactly the same). And I couldn't turn it on (.Net6 / .Net7) 🤔 :

    [STAThread]
    static void Main()
    {
        Application.SetDefaultFont(new Font(Control.DefaultFont.FontFamily, 7, FontStyle.Bold));
        Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
        Application.SetDefaultFont(new Font(Control.DefaultFont.FontFamily, 7, FontStyle.Bold));
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

no effect :(

@dreddy-work

Copy link
Copy Markdown
Member
  1. Main problem is that after PermonitorV2 switch all fonts are total mess. The video below is .Net6 (.Net7 the same but I recorded .Net6 to explicitly exclude my bugs). label1 using system font and label3 explicit font. Radio button click here do nothing - simple break point trigger:

@kirsan31 Thank you for continuing on this. In this gif, i see you changed Font and i see Font on the label changed except Default Font. I did not get fully on what exactly going wrong here vs expectations. Can you demonstrate issue within the app layout ( not cached values in source) and how is this different in various DPI modes here?

@dreddy-work

Copy link
Copy Markdown
Member

2. A common problem (not PermonitorV2 only) - when we use both DPI scale and SysFont scale font sizes behave differently then when these techniques are used alone:

This is how Winforms designed. When set DPI mode, Font change won't affect unless control itself is a common control and depend on Font( ex: Label). For this exercise, lets just focus on the Font mode ( and make sure we don't regress in DPI modes). DPI mode, we can open discussion on separate thread.

@kirsan31

kirsan31 commented Feb 9, 2022

Copy link
Copy Markdown
Contributor Author

@kirsan31 Thank you for continuing on this. In this gif, i see you changed Font and i see Font on the label changed except Default Font. I did not get fully on what exactly going wrong here vs expectations. Can you demonstrate issue within the app layout ( not cached values in source) and how is this different in various DPI modes here?

The problem with new functionality + PermonitorV2 demonstrated in the last video of the 1 post. And in this video I show the main reason for it - font change to something undesired after DPI switch. label1 using system font and label3 explicit font (Tahoma 9 + bold). We start the app with 125% DPI (same if we start with 100%):
image

Then we switch DPI to 100% and both fonts became 7 size 😮 :
image

This is how Winforms designed. When set DPI mode, Font change won't affect unless control itself is a common control and depend on Font( ex: Label). For this exercise, lets just focus on the Font mode ( and make sure we don't regress in DPI modes). DPI mode, we can open discussion on separate thread.

Apparently I confused you - sorry. All screens in my previous post with AutoScaleMode.Font by DPI scale and SysFont scale I mean changing system DPI and system font size - this:
image

@dreddy-work

Copy link
Copy Markdown
Member

@kirsan31, Sorry for the delayed response. I will go over this again this week and try to bring this to internal review soon.

@dreddy-work

Copy link
Copy Markdown
Member

@kirsan31, thank you so much getting this prototype so far. We discussed this proposal internally and conceptually agreed on it. Given the complexity involved at runtime layout and its impact on the designer serialization (design-time), we would want to wait on this until we add DPI scaling support fully to winforms runtime. We also have a Proposal about serializing the layout info ( i.e size , width etc) in logical units ( 100% DPI) that may also be impacted by this.

@kirsan31

Copy link
Copy Markdown
Contributor Author

@dreddy-work

and its impact on the designer serialization (design-time)

I want to add some clarification here - this PR have NO impacts on designer (besides some new properties).

Initial goal is - font scale controls with explicitly font set. The problem is that currently runtime scale control only if it use system font (no font was manually set). Can be solved with 2 approach:

  1. We not change runtime and do it through System font scaling - scale controls with explicitly specified font #3263. This is the first thing that came to my mind. But this approach have 2 drawbacks:
    1. It's too complex to implement.
    2. It will work only with SystemAware (will not work on the fly).
  2. Change runtime behavior (scale controls with manually set font) and not change designer at all - this PR. This is more simple solution and have no problems to work on the fly in the future...
@dreddy-work

Copy link
Copy Markdown
Member

I want to add some clarification here - this PR have NO impacts on designer (besides some new properties).

@kirsan31, we are reacting to the property value here and changing the Font value at runtime. I believe it impacts the serialization of the designer. You can try following to confirm.

  1. Get updated with binaries form this PR for new behavior
  2. Open the designer of your sample app in this PR.
  3. Change text size setting. This should impact the designer and try scale up/down font
  4. Modify designer (to trigger reserialization) by adding a button or changing a text property etc.
  5. Compare designer generated source before and after.
@kirsan31

Copy link
Copy Markdown
Contributor Author

I want to add some clarification here - this PR have NO impacts on designer (besides some new properties).

@kirsan31, we are reacting to the property value here and changing the Font value at runtime. I believe it impacts the serialization of the designer. You can try following to confirm.

  1. Get updated with binaries form this PR for new behavior
  2. Open the designer of your sample app in this PR.
  3. Change text size setting. This should impact the designer and try scale up/down font
  4. Modify designer (to trigger reserialization) by adding a button or changing a text property etc.
  5. Compare designer generated source before and after.

Indeed, I didn't think of that scenario... 😟

@ghost

ghost commented Sep 30, 2023

Copy link
Copy Markdown

The current status of this "draft" PR has persisted for over 180 days, making it highly probable that it is no longer aligned with the latest codebase. Our repository is set up to automatically close draft PRs that have become outdated, and it requests the author to revisit and reopen them if they deem it necessary, thereby bringing them to the team's attention.

@ghost ghost locked as resolved and limited conversation to collaborators Oct 30, 2023
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

api-suggestion (1) Early API idea and discussion, it is NOT ready for implementation draft draft PR on-hold

2 participants