Winforms: Allow set font application-wide

Created on 21 Mar 2020  路  13Comments  路  Source: dotnet/winforms

Is your feature request related to a problem? Please describe.

The default font has been updated in .NET Core 3.0 (#656) and documented. However for some users there is still an element of surprise when they migrate their apps to .NET Core.
We've received several questions regarding different sizes of forms (e.g. https://github.com/dotnet/winforms/issues/1122, https://github.com/dotnet/winforms/issues/1827, etc.).

Whilst the new default font is here to stay, some users may wish to retain the original font (e.g. due to a design of their app). However for an application with more than a handful of forms, setting the original font may be tedious and cumbersome exercise.

Describe the solution you'd like

Add the ability to set an application-wide font, similar to SetHighDpiMode() or SetCompatibleTextRenderingDefault() methods.

  • This method must be "run only once" kind, i.e. a user may not be allowed to invoke it once an app has started.
  • Any form that doesn't explicitly specify its own font, must inherit the application default font.

API Proposal

```C#
namespace System.Windows.Forms
{
public partial class Application
{
public void SetDefaultFont(Font font);
}
}

### API Usage

```C#
class Program
{
    [STAThread]
    static void Main()
    {
        Application.SetHighDpiMode(HighDpiMode.SystemAware);
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        Application.SetDefaultFont(new Font(new FontFamily("Microsoft Sans Serif"), 8f));

        Application.Run(new Form1());
    }
}

Will this feature affect UI controls?

No

api-approved api-suggestion

Most helpful comment

  • This method must be "run only once" kind, i.e. a user may not be allowed to invoke it once an app has started.

Are you going to throw an exception when the SetDefaultFont is called after Run? If so, I'd throw InvalidOperationException.

I propose we follow the same pattern set by SetCompatibleTextRenderingDefault() method and throw if SetDefaultFont() is called after the application has started:
https://github.com/dotnet/winforms/blob/18f1c8101085fd60a3eda7c95c796edc86c65820/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs#L1208-L1215

The rationale behind it, if a form has been created, it may have been laid out and rendered using one font, the font may have been cached etc., and setting a new font could be detrimental from both performance and UX.

All 13 comments

We should totally do this for .NET 5, I think this is a great idea.

  • This method must be "run only once" kind, i.e. a user may not be allowed to invoke it once an app has started.

Are you going to throw an exception when the SetDefaultFont is called after Run? If so, I'd throw InvalidOperationException.

  • This method must be "run only once" kind, i.e. a user may not be allowed to invoke it once an app has started.

Are you going to throw an exception when the SetDefaultFont is called after Run? If so, I'd throw InvalidOperationException.

I propose we follow the same pattern set by SetCompatibleTextRenderingDefault() method and throw if SetDefaultFont() is called after the application has started:
https://github.com/dotnet/winforms/blob/18f1c8101085fd60a3eda7c95c796edc86c65820/src/System.Windows.Forms/src/System/Windows/Forms/Application.cs#L1208-L1215

The rationale behind it, if a form has been created, it may have been laid out and rendered using one font, the font may have been cached etc., and setting a new font could be detrimental from both performance and UX.

Is there already a way to get the default font? (Get/set symmetry)

probably Control.DefaultFont ?

Might be worthwhile to add a corresponding GetDefaultFont() to Application so that folks can just tweak parts, like:

```C#
[STAThread]
static void Main()
{
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);

// Set default to 10pt
var font = Application.GetDefaultFont();
font = new Font(font.FontFamily, 10f);
Application.SetDefaultFont(font);

Application.Run(new Form1());

}
```

It would be odd if users had to call Control.DefaultFont to do this.

I don't think fonts are mutable, you have to construct a new one. (Not arguing against Application.GetDefaultFont for discoverability.)

I don't think fonts are mutable, you have to construct a new one. (Not arguing against Application.GetDefaultFont for discoverability.)

Fine, be like that ;-) Fixed sample.

The rationale behind this FR is to allow users to set the original font, that may have been used to design the app (i.e. _Font-scaling pixel-perfect_ design scenario), to help with a migration from .NET Framework to .NET Core/.NET.
To this end, users are expected to set both FontFamily and FontSize explicitly, and not leverage the current default font.

I don't feel that leveraging the default font to change its properties fits the above scenario. And, to be honest, I'm struggling to think of a use-case that would require this.
Do you have a use-case that would necessitate this?

Bump 馃槈

No objections, you're the domain expert. We just generally strive to avoid asymmetries like set-only APIs.

We just generally strive to avoid asymmetries like set-only APIs.

So do we, but in this case we want to have set-once kind of API, akin to SetHighDpiMode() or EnableVisualStyles().
Thank you

Reviewed and approved offline:

C# namespace System.Windows.Forms { public partial class Application { public void SetDefaultFont(Font font); } }

Was this page helpful?
0 / 5 - 0 ratings