Setting/Getting HighDpiMode in WinForms Core Apps
See original GitHub issueRationale
Developers in WinForms Core currently have no way to set the HighDPI mode in their WinForms App. In a future version of .NET Core 3.0, this will again be possible via App.Manifest; however, a change in the settings requires then their app to be rebuilt. The previous option in the classic framework to control this setting via App.Config has been completely dropped in .NET Core. Currently, the only way to set the HighDPIMode is via P/Invoke. The Application.SetHighDpiMode
method and Application.HighDpiMode
property are an easy to apply and to discover alternative.
Proposed API
namespace System.Windows.Forms
{
public sealed class Application
{
// Existing methods/properties (excerpt)
public static void EnableVisualStyles();
public static bool RenderWithVisualStyles { get; }
// Proposed method/property
public static bool SetHighDpiMode(HighDpiMode highDpiMode);
public static HighDpiMode HighDpiMode { get; }
}
public enum HighDpiMode
{
DpiUnaware,
SystemAware,
PerMonitor,
PerMonitorV2,
DpiUnawareGdiScaled
}
}
Description
Following EnableVisualStyles()
/RenderWithVisualStyles
of the Application
class, we propose the method SetHighDpiMode
which switches to the corresponding HighDPI mode, if that HighDPIMode setting a) has not been set before by other means (App.Manifest, P/Invoke before Application.Run
– in this case the value to be set is ignored), and b) that HighDPIMode
setting was set via SetHighDpiMode
before calling Application.Run
(or the first UI Element has been rendered).
Possible settings values are provided by the HighDpiMode
Enum:
DpiUnaware
SystemAware
PerMonitor
PerMonitorV2
DpiUnawareGdiScaled
If a setting is attempted to be set which is not supported by the underlying OS, SetHighDpiMode
automatically assumes the next possible setting on that OS; SetHighDpiMode never directly triggers an exception, but gives feedback as to whether the setting could be successfully set (true
) or not (false
).
In addition developers can query the actual setting of the current HighDpiMode at any time using the Application.HighDpiMode
property, which returns one of the available HighDpiMode
Enum values.
In the current implementation, we should limit the method/property to the process DpiAwareness rather than a Window DpiAwareness, and should probably think about extending this to a static method/property of the Control class to the windows DpiAwareness (@Tanya-Solyanik, thoughts?).
Issue Analytics
- State:
- Created 5 years ago
- Reactions:4
- Comments:14 (12 by maintainers)
FYI, steps to set DPI Awareness using the manifest file:
Add application manifest to your .NET Core project.
Uncomment the DPI-Awareness element, dpiAwareness element is supported as well., as manifest resource is processed by the windows code same as it is processed for a native app.
I agree that supporting high dpi is currently very challenging (to put it nicely) in winforms. I did a quick search in the winforms codebase and there is a lot of code in the individual controls to deal with this issue. I think the best (maybe only?) way to actually fix it completely would be to use effective pixels like on UWP/WPF. This way, most applications will not have to deal with handling different scaling factor at all (maybe only provide bitmap images in multiple sizes). The transformation between effective and physical pixels can then be handled by the low level rendering code.