Skip to content
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

[Proposal] Streamline application configuration and bootstrap #4909

Open
RussKie opened this issue May 14, 2021 · 0 comments
Open

[Proposal] Streamline application configuration and bootstrap #4909

RussKie opened this issue May 14, 2021 · 0 comments

Comments

@RussKie
Copy link
Member

@RussKie RussKie commented May 14, 2021

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
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.
image

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:

  1. Enhance the VB Application Framework in the same way as it was done for HighDpiMode (see #3705). This requires changes on the VS side.
  2. 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)
  3. 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.

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 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.
  • Whilst developers who build their apps on .NET Framework 4.7+ maybe familiar with app.config ApplicationConfigurationSection and/or app.config AppContextSwitchOverrides, we have removed all dependencies on app.config and these quirks which those two provided in .NET Core 3.0 timeframe.

    💭 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").
image

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):

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:

  1. 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.
  2. 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.
  3. Also check for Application.SetHighDpiMode(HighDpiMode) in the application's entry method - either the default static void Main() or as specified by StartupObject property.
  4. If there are multiple values are detected warn the developer.
  5. 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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
1 participant