0

Here is the situation: I have a form frmCompanyMasterEdit which inherits frmBaseEdit, which inherits frmBase, which inherits System.Windows.Forms.Form. These are all WinForms.

So, I am trying to get frmCompanyMasterEdit (a form that lets the user edit details about a company; really all forms but this is just for example) to be 4K compatible, which is why I have changed the property from Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font to Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi in all of the mentioned forms on the inheritance chain (frmBase, frmBaseEdit, frmCompanyMaster).

The problem is that it is far too big when I view it on a 4k (3840x2160) display scaled at 200%. The forms were doing great beforehand, but all I did was change this one property and it made my forms huge when I pull them up now. I am not sure why. I am using VB.NET, Visual Studio 2017 running Windows 10. We don't have the resources to upgrade to WPF.

frmBase.designer.vb - Me.AutoScaleDimensions = New System.Drawing.SizeF(192.0!, 192.0!)

app.manifest file below

<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
        <!-- UAC Manifest Options
            If you want to change the Windows User Account Control level replace the 
            requestedExecutionLevel node with one of the following.

        <requestedExecutionLevel  level="asInvoker" uiAccess="false" />
        <requestedExecutionLevel  level="requireAdministrator" uiAccess="false" />
        <requestedExecutionLevel  level="highestAvailable" uiAccess="false" />

            Specifying requestedExecutionLevel node will disable file and registry virtualization.
            If you want to utilize File and Registry Virtualization for backward 
            compatibility then delete the requestedExecutionLevel node.
        -->
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- A list of all Windows versions that this application is designed to work with. 
      Windows will automatically select the most compatible environment.-->

      <!-- If your application is designed to work with Windows Vista, uncomment the following supportedOS node-->
      <!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"></supportedOS>-->

      <!-- If your application is designed to work with Windows 7, uncomment the following supportedOS node-->
      <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>-->

      <!-- If your application is designed to work with Windows 8, uncomment the following supportedOS node-->
      <!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"></supportedOS>-->

      <!-- If your application is designed to work with Windows 8.1, uncomment the following supportedOS node-->
      <!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>-->

    </application>
  </compatibility>

  <!-- Add in each application's manifest to make application DPI aware-->
  <asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:windowsSettings
         xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>True</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>

  <!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
  <!-- <dependency>
    <dependentAssembly>
      <assemblyIdentity
          type="win32"
          name="Microsoft.Windows.Common-Controls"
          version="6.0.0.0"
          processorArchitecture="*"
          publicKeyToken="6595b64144ccf1df"
          language="*"
        />
    </dependentAssembly>
  </dependency>-->

</asmv1:assembly>

Title edit: sorry, not "4K compatible" since they're technically compatible in 4k, I meant to look good / sharp in 4K.

Chris K
  • 369
  • 1
  • 4
  • 11
  • I have declared as dpi aware (`True`) in the app.manifest but the form is still huge. Thinking it has to do with anchoring? – Chris K Feb 20 '18 at 22:00
  • I meant that they look great but not in 4K, hence why I'm trying to get them to. Forget the picture, I meant that it is supposed to look like that but for higher DPI / 4K. – Chris K Feb 21 '18 at 14:48
  • First, make a backup if you haven't already done so. Open the `frmBase.designer.vb` file and look for the line that sets `AutoScaleDimensions`. Copy that line and edit your question to include that line. Edit all the other forms `*.designer.vb` files and delete the `AutoScaleDimensions` and `AutoScaleMode` assignment lines. Those two properties should be inherited from `frmBase.designer.vb`. Ping me (include @TnTinMN in the comment) after you posted the requested info. – TnTinMn Feb 21 '18 at 15:20
  • @TnTinMn Added requested info – Chris K Feb 21 '18 at 15:47
  • Ok, the (192.0!, 192.0!) AutoScaleDimensions concern me. Typically, you design for '(96.0!, 96.0!)` and then let the autoscaling make its adjustments. This has been a long time pain of the WinForms designer has it likes to overwrite those settings when you edit the form. This always makes my head spin, but try editing the values in `frmBase.designer.vb` to be (96.0!, 96.0!)` without the designer open and recompile/run it. It may make things worse depending on how the form was originally designed. – TnTinMn Feb 21 '18 at 16:35
  • Weird, I did as you said (with the AutoScaleDimensions) and now the form is not "huge" but it is a bit small and the labels and textboxes are close together. – Chris K Feb 21 '18 at 17:20
  • It's funny, if I do nothing else (just leave the AutoScaleDimensions and AutoScaleMode as the were before I touched anything which was Font) and just add the app.manifest code (to make DPI aware) then it looks almost perfect other than my c1Lists not taking up the whole space and other little things – Chris K Feb 21 '18 at 18:44

1 Answers1

1

My advise for designing forms to scale to different DPI's is to avoid the defaults that the designer sets.

In the designer, set the AutoScaleMode to Inherit and not the default Font. Then add a default Constructor (Public Sub New()) to the form's code and define the auto-scaling info there.

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

The AutoScaleDimensions property is set to what historically has been the base DPI of display devices (screens), 96 DPI.

By declaring these properties in the constructor versus the designer generated InitializeComponent` method, you do lose the scaling in the designer view for this specific form; the scaling will be applied at run-time. Any form that inherits from it will be displayed with scaling applied in the designer and should appear to have the same size as when run.

Next, manifest (add a app.manifest) the application to declare it DPI aware. There are various options for DPI awareness, but the basic from is:

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

Weird, I did as you said (with the AutoScaleDimensions) and now the form is not "huge" but it is a bit small and the labels and textboxes are close together.

Fixing this after the damage has been done by VS overwriting factors based on the current design environment, is a game of trial and error. If the form appears to small, try a different base scale factor. Since (96.0!, 96.0!) is too small, a reasonable next attempt would be (120.0!, 120.0!); i.e. the form was originally designed at a 125% (96 * 1.25 = 120) zoom factor.

Finally, make sure the form looks proper at all display resolutions/DPI configurations. You may need to implement a specific scaling mechanism for some configurations.

TnTinMn
  • 11,522
  • 3
  • 18
  • 39
  • Aha. All I had to do is: make dpi-aware in the manifest (via the above code), and then add the below two lines to all of my form's designer.vb files: `Me.AutoScaleDimensions = New System.Drawing.SizeF(96.0!, 96.0!)` and `Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi`. My SizeF was set to `6.0!, 13.0!` rather than 96.0. Thank you @TnTinMn! – Chris K Feb 22 '18 at 15:15
  • But you're right, it's fine at 4k but not at 1920x1080, it's a bit blurry there – Chris K Feb 22 '18 at 16:20
  • Winforms was neglected for a long time, but has slowly been getting high DPI support in the last few .Net versions (I think it started getting updated with 4.5). Target the highest possible version you can. see: [High DPI support in Windows Forms](https://learn.microsoft.com/en-us/dotnet/framework/winforms/high-dpi-support-in-windows-forms) for some info. – TnTinMn Feb 22 '18 at 16:36
  • I have the 4.7 framework and tried the per monitor modern way described. It looks great in 4k as before (with the minor anchoring issues that I can fix); and in 1080p it's not blurry either but now everything is so big that it barely fits on the screen (like it's mobile or something). Will troubleshoot some more. Worst case scenario I will leave it the old way where it is a bit blurry in 4K but looks perfect in 1080p, since in reality we use the 1080p the most. – Chris K Feb 23 '18 at 19:56