Reputation: 751
I've got this down to a very simple repro, and cannot figure out what is going wrong with this form. When run at 96 DPI / 100% scale it appears fine:
But when run at 144 DPI / 150% scale (or even 96 DPI / 150% scale), everything scales except the form height:
Originally I thought this was a DPI issue, but after verifying that it repros at 96 DPI, I'm not sure what's going on.
There is nothing special going on with the dialog or control, other than specifically setting the font of the dialog, and setting the AutoScaleMode to DPI. The form lives inside an assembly that is loaded automatically by the app.
I'm using .NET 4.7.2 and Windows 10.
Here's the form code:
using System;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FormTestLib
{
partial class ValidatingSplash : Form
{
public ValidatingSplash()
{
InitializeComponent();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.CenterToParent();
}
}
}
Here's the designer file:
namespace FormTestLib
{
public partial class ValidatingSplash
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ValidatingSplash));
this.lblValidating = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lblValidating
//
this.lblValidating.Anchor = System.Windows.Forms.AnchorStyles.None;
this.lblValidating.AutoSize = true;
this.lblValidating.Location = new System.Drawing.Point(58, 45);
this.lblValidating.Name = "lblValidating";
this.lblValidating.Size = new System.Drawing.Size(166, 13);
this.lblValidating.TabIndex = 7;
this.lblValidating.Text = "Validating cached credentials...";
//
// ValidatingSplash
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.ClientSize = new System.Drawing.Size(274, 104);
this.ControlBox = false;
this.Controls.Add(this.lblValidating);
this.Font = new System.Drawing.Font("Segoe UI", 8.25F);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ValidatingSplash";
this.Text = "Validating Credentials";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblValidating;
}
}
In the app.config I'm setting DpiAwareness according to the docs:
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2"/>
</System.Windows.Forms.ApplicationConfigurationSection>
And in the manifest I'm setting the compatibility:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- Windows 10 compatibility -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
All this according to the instructions for high DPI support here.
The application code simply shows the dialog:
namespace TestApp
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// set the visual styles
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(true);
ValidatingSplash Splash = new ValidatingSplash();
Splash.ShowDialog();
}
}
}
Can anyone see what I might be doing wrong, or what I'm missing?
Thanks in advance!
Upvotes: 1
Views: 3035
Reputation: 130
To follow Microsoft guidelines and provide High DPI support for your application you should change several things.
First of all in your Designer file of form change AutoScaleDimensions to AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
. And AutoScaleMode to this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
.
In the application just use Application.SetCompatibleTextRenderingDefault(false);
I also added a small correction for for setting ClientSize of the form. AdjustClientWidthToDPIScale(). Depending on DPI scale the client width of form is changed according to the DPI factor.
All code is listed below.
App.config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.1"/>
</startup>
<System.Windows.Forms.ApplicationConfigurationSection>
<add key="DpiAwareness" value="PerMonitorV2" />
</System.Windows.Forms.ApplicationConfigurationSection>
</configuration>
Form code:
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace FormTestLib
{
public partial class ValidatingSplash : Form
{
public ValidatingSplash()
{
InitializeComponent();
AdjustClientWidthToDPIScale();
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
this.CenterToParent();
}
private void AdjustClientWidthToDPIScale()
{
double dpiKoef = Graphics.FromHdc(GetDC(IntPtr.Zero)).DpiX / 96f;
int compansatedWidth = (int)(ClientSize.Width * dpiKoef);
this.ClientSize = new Size(compansatedWidth, this.ClientSize.Height);
}
[DllImport("User32.dll")]
private static extern IntPtr GetDC(IntPtr hWnd);
}
}
Form designer:
namespace FormTestLib
{
partial class ValidatingSplash
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ValidatingSplash));
this.lblValidating = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// lblValidating
//
this.lblValidating.Anchor = System.Windows.Forms.AnchorStyles.None;
this.lblValidating.AutoSize = true;
this.lblValidating.Location = new System.Drawing.Point(58, 45);
this.lblValidating.Name = "lblValidating";
this.lblValidating.Size = new System.Drawing.Size(166, 13);
this.lblValidating.TabIndex = 7;
this.lblValidating.Text = "Validating cached credentials...";
//
// ValidatingSplash
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(274, 104);
this.ControlBox = false;
this.Controls.Add(this.lblValidating);
this.Font = new System.Drawing.Font("Segoe UI", 8.25F);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
//this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "ValidatingSplash";
this.Text = "Validating Credentials";
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label lblValidating;
}
}
Apllication code:
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ValidatingSplash Splash = new ValidatingSplash();
Splash.ShowDialog();
}
Upvotes: 3