Thursday, October 2, 2014

Using WPF user control in Winform application brings issue on a High-DPI display setting, and solution

Problem

One of our Winform applications uses a WPF user control, which is hosted in a System.Windows.Forms.Integration.ElementHost control. It worked fine until recently we tried to run it on a new 10-inch tablet which has Windows 8.1 as the OS. The font of the app became very tiny on the screen and almost unreadable. The resolution of the tablet was 1920 * 1200 and the DPI was set to 'Large', which was 144(150%), which was the default Windows 8.1 setting on this tablet. Our other Winform applications which did not using WPF control were scaled automatically to the normal, human-readable size. Only this one with WPF control had the problem.

I searched on Google about ElementHost scale problem something like that and found that some people using ElementHost or WPF control in Winform application encountered similar problem, but no one provided a valid solution.

Solution

After a couple of hours research, I finally found a very simple solution -- adding <dpiAware> to the application manifest. Here is an example from Microsoft's website.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
  <asmv3:application>
    <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>True</dpiAware>
    </asmv3:windowsSettings>
  </asmv3:application>
</assembly>

For my case, I need to set the <dpiAware> to  Per-monitor to make it work normally. That is, change the line in the middle to <dpiAware>Per-monitor</dpiAware>. The differences between each value are listed below(These are from MSDN, for more detail information, please see the reference links below).
DPI awareness manifest valueDescription
FalseSets the application to not DPI-aware.
TrueSets the application to system DPI–aware.
Per-monitorOn Windows 8.1, sets the application to per monitor-DPI aware. On Windows Vista through Windows 8, sets the application to not DPI–aware.
True/PMOn Windows 8.1, sets the application to per monitor-DPI aware. On Windows Vista through Windows 8, sets the application to system-DPI aware.

So that is something about DPI-Aware application. For those who is interested in how to write a DPI-Aware application, there are some very detailed contents on Microsoft's website:

Tutorial: Writing High-DPI Win32 Applications

Writing DPI-Aware Desktop and Win32 Applications

Developing a Per-Monitor DPI-Aware WPF Application