Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WinForms 4K and 1080p scaling / high DPI?

So, here is the scenario: I am trying to make all of my forms (which are Winforms) look good in 4K and 1080p also known as high-DPI or "dpi-aware". I (for the purpose of this question) have three forms: frmCompanyMasterEdit which inherits from frmBaseEdit which inherits from frmBase, which inherits form System.Windows.Forms.Form.

I have tried the old way, by making my application DPI-aware in the manifest:

  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>

That way, other than minor anchoring issues which I can fix, the form looks perfect at 4K and looks just like that but a bit blurrier in 1080p. Here it is in 4K: 4K both old and new ways.

Anyway, so I scratch that and try it the new way described in .NET 4.7, targeting the 4.7 framework and adding the following code:

to app.config

<System.Windows.Forms.ApplicationConfigurationSection>
   <add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>

to app.manifest

<!-- Windows 10 compatibility -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />

and also taking the old code out of the app.manifest so as to not override the new .NET 4.7 way. I made sure to put the code in the appropriate places. So here the form looks good in 4K as the image above but now in 1080p it is very zoomed in as shown here: 1080p new way

So either way, the form looks great in 4k other than minor anchoring issues, and it either (the old way) is the right size but a bit blurry in 1080p or is not blurry in 1080p but is really zoomed in. I also had to change these two lines in all the designer.vb files as shown below:

Me.AutoScaleDimensions = New System.Drawing.SizeF(96.0!, 96.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi

I don't know why I just can't get it looking appropriate in 1080p. Like I said, I am targeting the 4.7 .NET framework. I am running on the appropriate version of Windows 10 (Version 1709 / Creator's edition). The 1080p is scaled at 100%. Also, we do not have the resources to upgrade to WPF.

like image 421
Chris K Avatar asked Feb 27 '18 15:02

Chris K


People also ask

What does enable high DPI scaling mean?

High DPI displays have increased pixel density, compared to standard DPI displays. Pixel density is measured in Dots per Inch (DPI) or Pixels per Inch (PPI), and is determined by the number of display pixels and their size.

Does DPI affect scaling?

If the DPI changes, the application does not adjust to the new DPI value. It will be automatically scaled up or down by the system when the DPI changes from the system value.

How do I fix DPI scaling issues for Visual Studio 2019?

There are three options to resolve the display problem: Restart Visual Studio as a DPI-unaware process. Add a registry entry. Set your display scaling setting to 100%


1 Answers

I've successfully added DPI support for 2 of my Winforms applications targeting .NET 4.5 and 4.7 respectively.

In the past, I tried adding support via a manifest file with no luck. Fortunately, I found the following solution:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WinformsApp
{
    static class Program
    {
        [DllImport("Shcore.dll")]
        static extern int SetProcessDpiAwareness(int PROCESS_DPI_AWARENESS);

        // According to https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx
        private enum DpiAwareness
        {
            None = 0,
            SystemAware = 1,
            PerMonitorAware = 2
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            SetProcessDpiAwareness((int)DpiAwareness.PerMonitorAware);

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

The above code is what your Program.cs file should look like. Of course, you'll have to port this to VB, but it should be easy enough to do.

This worked perfectly in Windows 10 without the need for any other modification.

In one of the two Winforms applications I was rendering strings through the Graphics class using pixel coordinates, which caused my strings to be offset. The fix was pretty trivial:

private void DrawString(Graphics g, string text, int x, int y)
{
    using (var font = new Font("Arial", 12))
    using (var brush = new SolidBrush(Color.White))
        g.DrawString(text, font, brush, LogicalToDeviceUnits(x), LogicalToDeviceUnits(y));
}

Basically, I had to use Control.LogicalToDeviceUnits(int value) to get the pixel coordinates to scale.

Other than that, I didn't need to touch my code at all.

like image 75
Nolonar Avatar answered Oct 08 '22 17:10

Nolonar