dotnet / winforms

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

Text is looking blurred after change the scale in a system with High DPI settings. #8376

Open SathiyathanamSathish opened 1 year ago

SathiyathanamSathish commented 1 year ago

.NET version

.Net 6

Did it work in .NET Framework?

Yes

Did it work in any of the earlier releases of .NET Core or .NET 5+?

No.

Issue description

The text is looking blurred after change the scale settings in a system. We have added the below settings in our App.Config file.

image

Kindly share your suggestions if we have missed anything?

Steps to reproduce

You can refer the below video to reproduce the issue.

https://user-images.githubusercontent.com/89458634/207322835-0292f9e1-c73e-4cd4-8e65-c6ffeb489d52.mp4

Sample : DPI_Test.zip

kirsan31 commented 1 year ago

App.Config is obsolete technique - don't use it. Use Project-level application settings (see for tips in your Program.cs file) or Application.HighDpiMode property.

dreddy-work commented 1 year ago

As @kirsan31 pointed out, app.config has limited functionality in .NET and high DPI related functionality is moved to project/application-level settings.

vijayarasan commented 1 year ago

@dreddy-work / @kirsan31 ,

We have checked the suggested solution. But it is not working properly. Still, we have facing the TextBlurred issue. Also, we have checked the HighDpi support by adding the app.manifest file. Find the sample in the attachment.

Sample: Sample.zip

We have faced a TextBlurred issue while changing the scaling at runtime only. If we stop and reload the application, then it will automatically work based on the last selected scale.

Can you please suggest any ideas to resolve the reported scenario?

kirsan31 commented 1 year ago

@vijayarasan

  1. Not use several dpi setting methods - use only one.
  2. Pls not use any other deprecated methods for dpi settings. Use that was advise above.
  3. Read this about different dpi modes: https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props-desktop#applicationhighdpimode
vijayarasan commented 1 year ago

@kirsan31,

When we have changing the system DPI settings in runtime the given font does not updated properly depending on the modified settings For example, We are running the winforms application with below shown system settings, image

Form display text shown below,

image

And change this settings in runtime shown below, image

The text on the form is not updating when the DPI is changed at runtime,

image

With that form size only changed depending on the modified system settings but the given text input remains the same size. Could you please check and share the ways to overcome this issue.

Here we have attached the issue reproduced sample Sample.zip

kirsan31 commented 1 year ago

And this is most likely a bug (or at least inconsistent behavior). The new font is created with the same height as before the DPI change. But if you restart the application, the font will be created with a changed height. /cc @dreddy-work

vijayarasan commented 1 year ago

@kirsan31,

if you are sure in this case that this is a bug, will you kindly fix this issue? We were also aware of this way of restarting applications in this issue. Could you offer an alternative approach or workaround to this issue?

kirsan31 commented 1 year ago

@vijayarasan I am not 100% sure - we need to wait for @dreddy-work to response about this... The bad thing is that we have waiting-author-feedback label here - developers may not look here until the author answers :(

dreddy-work commented 1 year ago

Changing DPI while application is running is not fully supported in DPI aware Winforms applications yet. Assuming restart of the application works as expected, this would be on lower priority. A similar request that @kirsan31 proposed here https://github.com/dotnet/winforms/pull/6580 is also on-hold at the moment.

vijayarasan commented 1 year ago

@dreddy-work ,

Thanks for the update. Please let us know once the required changes are included

kirsan31 commented 1 year ago

@dreddy-work I have some questions about your answer.

Changing DPI while application is running is not fully supported in DPI aware Winforms applications yet.

This is true. SystemAware is working somehow but PerMonitorV2 leaves much to be desired :( And I always thought that the main goal of a complete DPI overhaul in winworms is just a full support of PerMonitorV2 - am I wrong? This issue is about PerMonitorV2 and

Assuming restart of the application works as expected, this would be on lower priority.

looks weird 🤷‍♂️

A similar request that @kirsan31 proposed here https://github.com/dotnet/winforms/pull/6580 is also on-hold at the moment.

These is completely different problems. https://github.com/dotnet/winforms/pull/6580 is about system font size and scaling explicit fonts in the app - currently not working with any dpi mode. But this issue is about dpi settings font scaling, that PerMonitorV2 behave like SystemAware.

dreddy-work commented 1 year ago

Main goal of a complete DPI overhaul in winforms is just a full support of PerMonitorV2 - am I wrong?

Eventually we want to be there. PermonV2 mode is introduced by Windows in Windows, has greatly improved user experiences by allowing for on-the-fly handling of high DPI windows messages. In recent versions of Windows, the WM_GETDPISCALEDSIZE message has been improved that helps improe WinForms support font scaling in PermonV2 mode. In the first iteration, focus is on supporting PermonV2 mode in the majority of cases, and then consider expanding support to allow for on-the-fly DPI setting changes.

These is completely different problems I mentioned it in the context of changing Font on-the-fly.

kirsan31 commented 1 year ago

@dreddy-work

In the first iteration, focus is on supporting PermonV2 mode in the majority of cases, and then consider expanding support to allow for on-the-fly DPI setting changes.

I'm completely confused now. If we look here:

So, the main reason (the only difference to the user) for PerMonitor and PerMonitorV2 is exactly adjust scale factor when the DPI changes or as you say - on-the-fly DPI setting changes 🤷‍♂️ Or drugging window to other monitor is not the same as dpi setting change (I always thought it was the same)?

dreddy-work commented 1 year ago

Or dragging window to other monitor is not the same as dpi setting change (I always thought it was the same)?

Technically, there are no differences. However, we have encountered some reliability issues with Windows message notifications for on-the-fly DPI setting changes in earlier versions of Windows. As a result, handling on-the-fly DPI changes in WinForms was given lower priority. We are prioritizing the issues for this release with intention of maximum impact and are tracked here.

Just for my understanding, how common is the scenario for on-the-fly DPI settings change?

kirsan31 commented 1 year ago

@dreddy-work

Technically, there are no differences. However, we have encountered some reliability issues with Windows message notifications for on-the-fly DPI setting changes in earlier versions of Windows. As a result, handling on-the-fly DPI changes in WinForms was given lower priority.

It's a big surprise (I always test DPI related stuff by settings change) :(

Just for my understanding, how common is the scenario for on-the-fly DPI settings change?

To answer this, I need to ask one more question:

Connecting by rdp to win10 \ win11 machine (will automatically (by default) change dpi to client settings) will use monitor change (dragging to other) scenario, or system settings change scenario?

In case of second (system settings change), then the answer to your question is very often (may be more often then dragging to other monitor) ...

kirsan31 commented 1 year ago

/cc @dreddy-work We would really like to receive an answer to the question in the previous post, which arose as a consequence of your question...

dreddy-work commented 1 year ago

/cc @dreddy-work We would really like to receive an answer to the question in the previous post, which arose as a consequence of your question...

@kirsan31, I need to test this to determine the specific answers. The process should be the same for all scenarios as long as WinForms receives DPI messages from Windows. WinForms respond on these messages and try scaling accordingly. My concern was about the reliability of Windows messages in these scenarios. We have not yet incorporated testing for RDP/dynamically changing DPI scenarios. These will be manually validated. I will bring this up in an upcoming team meeting and discuss adding coverage for these areas in our current work.

If you are already utilizing your applications in PermonitorV2 mode, would you be willing to share them with us so we can add them to our test suite?

kirsan31 commented 1 year ago

@dreddy-work thank you for answer - we will wait for the results...

If you are already utilizing your applications in PermonitorV2 mode, would you be willing to share them with us so we can add them to our test suite?

Unfortunately no, PerMonitorV2 are far away from prod ready state :( We are using SystemAware with some custom manual fixes.

Interesting thing, I just got a report about a non-working PerMonitorV2 (when dragging on other screen), but with on the fly change settings everything work fine!

kirsan31 commented 1 year ago

@dreddy-work can you clarify how can it be?

Interesting thing, I just got a report about a non-working PerMonitorV2 (when dragging on other screen), but with on the fly change settings everything work fine!

Also, I think this behavior can help us got an answer to this question:

Connecting by rdp to win10 \ win11 machine (will automatically (by default) change dpi to client settings) will use monitor change (dragging to other) scenario, or system settings change scenario?

And I will defiantly check this...

dreddy-work commented 1 year ago

Interesting thing, I just got a report about a non-working PerMonitorV2 (when dragging on other screen), but with on the fly change settings everything work fine!

I'm only speculating, but it seems to be a case of zooming rather than scaling. You can debug to see if DataVIsualizationChart was getting in DPI_CHNAGED messages handling.

kirsan31 commented 1 year ago

I'm only speculating, but it seems to be a case of zooming rather than scaling.

Thanks, You were right, I set up PerMonitorV2 in project file, but forgot to call ApplicationConfiguration.Initialize(); 🤦‍♂️So app was running in SystemAware mode.

P.s. we have no docs on learn.microsoft.com for ApplicationConfiguration.Initialize();

RussKie commented 1 year ago

P.s. we have no docs on learn.microsoft.com for ApplicationConfiguration.Initialize();

It's not exactly so. Since this is a source generated API, it is a consumer API; it doesn't technically exist in the Windows Forms API set, and as a result, it doesn't exist in the intellisence set.... There are docs at https://aka.ms/applicationconfiguration, and that link is in the template for that reason. That said, I don't disagree that discoverabilty of information for this API could be improved.

We discussed the documention of such API, but we could not come up with a (reasonable) solution.

/cc: @gewarren for any further thoughts.

kirsan31 commented 1 year ago

@RussKie Docs for ApplicationConfiguration.Initialize(); itself is not a real problem. The real problem is that we have some settings in project file, that's means nothing without call to ApplicationConfiguration.Initialize(); Personally, I am stepping on this rake (forget to call this method) for at least the second time :( I think that it is necessary to generate a warning (during compilation or through the analyzer) if we have such settings in the project file, and there is no call to ApplicationConfiguration.Initialize();. And yes, of course, this is important mainly for projects that were created before .Net6.

RussKie commented 1 year ago

this is important mainly for projects that were created before .Net6.

Just to clarify - by that you mean 'existing projects that were migrated to .NET 6', right? If yes, those projects should have an existing app bootstrap code in Program.Main(), shouldn't they? And I expect, it would be a conscious decision to switch from those to the new application bootstrap. What am I missing here?

I think that it is necessary to generate a warning (during compilation or through the analyzer) if we have such settings in the project file, and there is no call to ApplicationConfiguration.Initialize();.

It would be great, but I don't think it's possible (I am not an expert in analyzers though). I.e., the analyzer won't be activated unless there's ApplicationConfiguration.Initialize() code. The MSBuild properties represent the metadata used by the analyzer. And it doesn't work in reverse - i.e., we can't query the metadata and check for absence of a code.

kirsan31 commented 1 year ago

@RussKie

Just to clarify - by that you mean 'existing projects that were migrated to .NET 6', right? If yes, those projects should have an existing app bootstrap code in Program.Main(), shouldn't they? And I expect, it would be a conscious decision to switch from those to the new application bootstrap. What am I missing here?

Yes, that is right. This is mainly about adding new functionality. For example, you want to enable PerMonitorV2 and remember that now this is done through the project file - you add them and remove extra code in Program.cs.

This is an example scenario of course, as I see it for myself. I don't know exactly how, but I've gotten settings in the project file twice (may be more) already without ApplicationConfiguration.Initialize().