Historically Windows Forms designer was rendering its design surface based on hardcoded assumptions, such as control default font and dpi settings. However over the past 10-15 years not only multi-monitor configurations became a norm, monitor tech has made significant process making 4K, 5K, 8K, etc. monitors widely used by our consumers. The Windows itself has been innovating and tinkering with UI configurations, such default font metrics, which over the years deviated from "Microsoft Sans Serif, 8pt" and now is set to "Segoe UI, 9pt".
The Windows Forms runtime has been (more or less) keeping up with the changes, e.g. providing a new API to set high dpi mode, or by updating the default font. The default font change has unearthed numerous issues in the runtime (e.g. different font-based scaling), which we considered addressing by providing (yet another) API to set an application-wide default font.
However during numerous discussions the team has identified probably the biggest flaw in the current separation of the runtime and the designer, and the overall move from .NET Framework assumptions - the lack of a mechanism to share Windows Forms project-level configuration settings between the runtime and the designer. That is, if the app is configured to run with disabled visual styles, in PerMonitorV2, and have an application-wide default font set to "Arial, 14pt" there is no way to show the designer surface with the same settings to truly provide the WYSIWYG experience.
Funnily enough Visual Basic apps are in a good position for the designer integration with their Application Framework functionality, i.e. "*.myapp" file. The C# project lack this mechanism, and traditionally have been a configuration-code-first approach.
Proposal
The purpose of this proposal is to
1 streamline a Windows Forms application configuration and bootstrap,
2. with the view that this will facilitate the sharing of the information between the runtime and the designer during the development phase. That is, whenever the designers surface process is started configuration information is read from a known location, and necessary configurations are applied (e.g. run the design surface in PerMonitorV2 mode, or set a form/usercontrol default font to "Arial, 14pt"). ⚠️out of scope, tracked under dotnet/winforms-designer#3192.
NOTE: The new functionality is opt-in, i.e. unless a developer makes a conscience decision to use the new configuration and the bootstrap mechanism existing applications will continue to work as-is, and the current developer experience will remain the same.
1. Visual Basic
For VB projects this known location is "myapp" file.
The designer surface process should have no issues reading configuration values from a myapp file.
There are a number of avenues we can take to facilitate an integrated devex such as:
Enhance the VB Application Framework in the same way as it was done for HighDpiMode (see #3705). This requires changes on the VS side.
Until the necessary changes on the VS side are done provide a workaround similar to the one performed for HighDpiMode in .NET 5.0 (see: #3894)
Alternatively we can consider departing from VBAF/myapp generators and replace those with a source generator. This will necessitate a separate investigation and proposal (out of scope).
Other points for further consideration:
How to read app.manifest/app.config for dpi values. See "How to resolve dpi settings?" below.
For C# projects the issue is little more involved. There are several candidates for storing settings, such as a csproj file, an app.config or a new configuration file.
After deliberations and discussions we propose the settings to be stored in the csproj file for the following reasons:
The designer surface process should have no issues reading configuration values from a myapp file.
Unlike schema enforced app.config, a csproj can contain an arbitrary set of settings, easily manageable and available to MSBuild process.
app.configs don't appear to be very popular in .NET apps.
💭 It is also worth noting that quirks were necessary in .NET Framework, which was installed in-place, and didn't provided any kind of side-by-side deployment. In a rare and unfortunate event where we may accidentally break end users experiences in a given release users will be able to install a previous working .NET release and run their application against it until a fix becomes available.
whilst there maybe an argument that app.config can be changed by users, thus altering behaviours of applications, and changes to csproj will require a recompilation, it is also worth noting that our SDK is built with developers in mind, and not the ability of users to alter the application behaviours at will. If an app developer feels it is important to allow the app users to change the default font or dpi settings via an app.config it is the developers responsibility to facilitate that mechanism to the users.
The runtime portion will leverage source generators to read configurations from the csproj, and emit code for the necessary API, e.g. call Application.SetHighDpiMode(HighDpiMode.PerMonitorV2) and Application.SetDefaultFont("Arial, 14pt").
With that we will be able to leverage the power of Roslyn analyzers to warn developers about duplicate/redundant API invocations performed outside the generated code.
3. Visual Studio (out of scope)
To complete the user experience we can consider leveraging (e.g. copying) VBAF property pages and provide the same experience to C# developers.
How to resolve dpi settings?
At this point an astute Windows Forms developer will say that there are currently 3 different ways to configure dpi settings (which may or may not be mutually exclusive or complimentary):
app.manifest - Common Control related configuration, dealing with it was always a pain. Very likely that a significant part of Windows Forms developers have never heard of it.
This proposal introduces a 4th way of configuring dpi, and to make it successful it has to (paraphrasing JRR Tolkien):
One API to rule them all, One API to find them, One API to bring them all and in the ProjectConfiguration bind them...
The benefit the new approach provides is by facilitating the sharing of the information between the runtime and the designer during the development phase, as well as unifying how dpi settings are configured. This benefit is believed to outweigh the need to remove several lines of code from Main() method and adding several properties into a cspoj file.
Here's how we plan to resolve a project's dpi settings:
If a custom app.manifest is specified, read it. It takes the precedence as it is used when the process is created, before Windows Forms runtime gets involved.
Since the runtime no longer reads any settings from the app.config we will ignore it. It is possible to use Roslyn analyzers to warn a developer that app.config switches are no longer supported.
Also check for Application.SetHighDpiMode(HighDpiMode) in the application's entry method - either the default static void Main() or as specified by StartupObject property.
If there are multiple values are detected warn the developer.
If no values are detected - use a default value we agree upon (e.g. PerMonitorV2).
Other considerations
The new source generator project will form a new Windows Forms artifact, and will be part of Windows Desktop bundle. It will also need to be references by a Windows Forms C# project by default.
The default C# template will need to be updated to replace the current project configurations with the new source generated method.
Plan the Roslyn analyzers taxonomy for warnings/errors, and other related considerations.
The text was updated successfully, but these errors were encountered:
Overview
Historically Windows Forms designer was rendering its design surface based on hardcoded assumptions, such as control default font and dpi settings. However over the past 10-15 years not only multi-monitor configurations became a norm, monitor tech has made significant process making 4K, 5K, 8K, etc. monitors widely used by our consumers. The Windows itself has been innovating and tinkering with UI configurations, such default font metrics, which over the years deviated from "Microsoft Sans Serif, 8pt" and now is set to "Segoe UI, 9pt".
The Windows Forms runtime has been (more or less) keeping up with the changes, e.g. providing a new API to set high dpi mode, or by updating the default font. The default font change has unearthed numerous issues in the runtime (e.g. different font-based scaling), which we considered addressing by providing (yet another) API to set an application-wide default font.
However during numerous discussions the team has identified probably the biggest flaw in the current separation of the runtime and the designer, and the overall move from .NET Framework assumptions - the lack of a mechanism to share Windows Forms project-level configuration settings between the runtime and the designer. That is, if the app is configured to run with disabled visual styles, in PerMonitorV2, and have an application-wide default font set to "Arial, 14pt" there is no way to show the designer surface with the same settings to truly provide the WYSIWYG experience.
Funnily enough Visual Basic apps are in a good position for the designer integration with their Application Framework functionality, i.e. "*.myapp" file. The C# project lack this mechanism, and traditionally have been a configuration-code-first approach.
Proposal
The purpose of this proposal is to⚠️ out of scope, tracked under dotnet/winforms-designer#3192.
1 streamline a Windows Forms application configuration and bootstrap,
2. with the view that this will facilitate the sharing of the information between the runtime and the designer during the development phase. That is, whenever the designers surface process is started configuration information is read from a known location, and necessary configurations are applied (e.g. run the design surface in PerMonitorV2 mode, or set a form/usercontrol default font to "Arial, 14pt").
NOTE: The new functionality is opt-in, i.e. unless a developer makes a conscience decision to use the new configuration and the bootstrap mechanism existing applications will continue to work as-is, and the current developer experience will remain the same.
1. Visual Basic
For VB projects this known location is "myapp" file.

The designer surface process should have no issues reading configuration values from a myapp file.
There are a number of avenues we can take to facilitate an integrated devex such as:
HighDpiMode(see #3705). This requires changes on the VS side.HighDpiModein .NET 5.0 (see: #3894)Other points for further consideration:
The final decision is TBD. /cc: @KlausLoeffelmann @KathleenDollard
2. C#
For C# projects the issue is little more involved. There are several candidates for storing settings, such as a csproj file, an app.config or a new configuration file.
After deliberations and discussions we propose the settings to be stored in the csproj file for the following reasons:
The runtime portion will leverage source generators to read configurations from the csproj, and emit code for the necessary API, e.g. call

Application.SetHighDpiMode(HighDpiMode.PerMonitorV2)andApplication.SetDefaultFont("Arial, 14pt").With that we will be able to leverage the power of Roslyn analyzers to warn developers about duplicate/redundant API invocations performed outside the generated code.
3. Visual Studio (out of scope)
To complete the user experience we can consider leveraging (e.g. copying) VBAF property pages and provide the same experience to C# developers.
How to resolve dpi settings?
At this point an astute Windows Forms developer will say that there are currently 3 different ways to configure dpi settings (which may or may not be mutually exclusive or complimentary):
Application.SetHighDpiMode(HighDpiMode).This proposal introduces a 4th way of configuring dpi, and to make it successful it has to (paraphrasing JRR Tolkien):
The benefit the new approach provides is by facilitating the sharing of the information between the runtime and the designer during the development phase, as well as unifying how dpi settings are configured. This benefit is believed to outweigh the need to remove several lines of code from
Main()method and adding several properties into acspojfile.Here's how we plan to resolve a project's dpi settings:
Application.SetHighDpiMode(HighDpiMode)in the application's entry method - either the defaultstatic void Main()or as specified byStartupObjectproperty.PerMonitorV2).Other considerations
The text was updated successfully, but these errors were encountered: