How to configure an app to run correctly on a machine with a high DPI setting (e.g. 150%)?
Once you go past 100% (or 125% with the "XP-style DPI scaling" checkbox ticked), Windows by default takes over the scaling of your UI. It does so by having your app render its output to a bitmap and drawing that bitmap to the screen. The rescaling of that bitmap makes the text inevitably look fuzzy. A feature called "DPI virtualization", it keeps old programs usable on high resolution monitors.
You have to explicitly let it know that you can handle higher DPI settings by adding the <dpiAware>
element to your manifest. The MSDN page is here but it isn't complete since it is omitting the UAC settings. Project + Add New Item, pick "Application Manifest File". Edit the manifest text or copy/paste this:
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<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">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
You can also pinvoke SetProcessDPIAware() in your Main() method, necessary for example if you deploy with ClickOnce:
[STAThread]
static void Main() {
if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); // Edit as needed
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
UPDATE, this common need is finally a bit easier if you use VS2015 Update 1 or higher. The added manifest already has the relevant directive, just remove the comments.
Keyword for search so I can find this post back: dpiAware
Metafile size incorrect in console app, correct in Windows Forms
Thanks to Hans Passant. His link was super helpful.
So even if EMF is a resolution-independent graphics file format, the resolution and DPI of your screen (likely the main screen) will influence the result. Basically, EMF uses the physical units of your screen. So for HiDPI screens, it depends on the screen scaling.
To fix it, the application needs to run in DPI aware mode. See below, for how to achieve it.
If run in the DPI virtualization mode instead, the EMF frame behaves differently from the EMF content and the result is incorrect. That's strange, likely a bug.
I've also noted that none of the results are in line with the EMF and EMF+ standards published by Microsoft. If they were, they wouldn't properly work in Microsoft Office. Now it nicely works in Microsoft Word.
DPI aware mode
Either call this SetProcessDPIAware()
at the start of your application:
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
Or use an application manifest:
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
How to configure an app to run correctly on a machine with a high DPI setting (e.g. 150%)?
Once you go past 100% (or 125% with the "XP-style DPI scaling" checkbox ticked), Windows by default takes over the scaling of your UI. It does so by having your app render its output to a bitmap and drawing that bitmap to the screen. The rescaling of that bitmap makes the text inevitably look fuzzy. A feature called "DPI virtualization", it keeps old programs usable on high resolution monitors.
You have to explicitly let it know that you can handle higher DPI settings by adding the <dpiAware>
element to your manifest. The MSDN page is here but it isn't complete since it is omitting the UAC settings. Project + Add New Item, pick "Application Manifest File". Edit the manifest text or copy/paste this:
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<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">
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
You can also pinvoke SetProcessDPIAware() in your Main() method, necessary for example if you deploy with ClickOnce:
[STAThread]
static void Main() {
if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1()); // Edit as needed
}
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
UPDATE, this common need is finally a bit easier if you use VS2015 Update 1 or higher. The added manifest already has the relevant directive, just remove the comments.
Keyword for search so I can find this post back: dpiAware
Windows Forms DPI scaling
Creating a DPI-Aware Application
All containers must use the same AutoScaleMode - this part fixed my problem
It is required that windows app should have same layout at different resolutions means there should be no effect on layout of app on changing resolution. Here are the steps to do this.
- Use table layout panel
- Drag control in cell of tablelayoutpanel and set anchor and dock property.
- Set rowspan and colspan properties of dragged control to merge cells
- Set margin and padding of dragged control with respect to cell.
- drag all controls and follow same steps, complete design using tablelayoutpanel
- Now set all columns and rows size of tablelayoutpanel = autosize (or in %)
- Set tablelayoutpanel properties autosize = true,autosizemode = grow and shrink
- Set Forms properties autosize = true,autosizemode = grow and shrink
- Run windows app If your windows app opens in maximum state then set tablelayoutpanel dock property =fill.
Related Topics
How to Load Dll (Module Could Not Be Found Hresult: 0X8007007E)
Post an HTML Table to Ado.Net Datatable
Deserializing Polymorphic Json Classes Without Type Information Using Json.Net
Convert List≪Derivedclass≫ to List≪Baseclass≫
Should 'Using' Directives Be Inside or Outside the Namespace
Process.Start: How to Get the Output
Parameterized Query For MySQL With C#
How to Check If a Number Is a Power of 2
The Provider Is Not Compatible With the Version of Oracle Client
Pre & Post Increment Operator Behavior in C, C++, Java, & C#
How to Call Asynchronous Method from Synchronous Method in C#
How to Display a Decimal Value to 2 Decimal Places