How to enable per-monitor DPI scaling in WPF to stop WPF windows appearing blurry

So you've put heaps of effort into developing an intuitive UI in WPF (Windows Presentation Foundation) only to notice it appears blurry when you drag the window over to another monitor or change your scaling settings (also known as DPI (dots per inch) scaling). Now your beautiful UI looks blurry and hard to read. This actually happens due to a compatibility feature in Windows that is designed to ensure user interfaces are big enough, while still laying out correctly and being usable. Windows uses a technique called bitmap stretching to increase the size of windows to match your scaling settings if it doesn't trust that the app will scale the UI correctly itself. Normally, this compatibility feature isn't needed for WPF since WPF has built in support for per monitor scaling, which means it can correctly scale both when the app initially opens and when windows are moved between monitors and when scaling settings of a monitor a WPF window is on changes. Other UI technologies such as GDI and Windows Forms aren't as good at scaling as WPF, especially if they need to scale while the app is running. This might be why WPF uses bitmap stretching by default when a window needs to change its scaling while the app is running - in case you use other UI frameworks within a WPF window such as Windows Forms through a WindowsFormsHost. Luckily, it's easy to disable this compatibility feature using the application manifest so that WPF can use its own in built scaling when a window needs to change its scaling.

WPF with bitmap stretching enabled vs disabled

The fix

To disable bitmap stretching and allow WPF to use its own scaling system when a window needs to change its scaling, we just need to specify this in the application manifest. By default, WPF app windows use WPF's scaling system to scale the UI according to the scaling settings of the primary monitor when the app was opened, but will be bitmap stretched if they need to change their scaling while the app is running. Note that if you're using the .Net Framework, you'll need to use version 4.6.2 or later. .Net Framework 4.6.2 comes preinstalled with Windows 10 Anniversary Update (Version 1607) and Windows Server 2016 and can be installed on Windows versions down to Windows 7 and Windows Server 2008 SP2, see more info this here.

Accessing the manifest

If you already know how to access your app's manifest, you can skip this step. Otherwise, to access the manifest in a C# WPF app, right click on your app's project in Visual Studio, then Add -> New item... -> Installed -> Application Manifest File then keep the default file name (which will probably be 'app.manifest') and click Add, Once you're done that, right click on your project again and this time select Properties. From here, find the Manifest property and select or type in the name (including the file extension) of the file you just created. A manifest has now been created for your app.

If you're using a VB WPF app, right click on the project and choose Properties, then find either the 'View Windows settings' button or 'Create or open app manifest for Windows settings' link and click it. This will open your app's manifest.

Modifying the manifest

Now open the manifest and add the following to the file in the assembly section:

   <application xmlns="urn:schemas-microsoft-com:asm.v3">

          <windowsSettings>

                <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>

                <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">permonitorv2,permonitor</dpiAwareness>

          </windowsSettings>

   </application>

That's it! Now run your app and feel free to move it between monitors and change your scaling settings without worrying about your UI being bitmap stretched! Since WPF was built from the ground up to support DPI scaling, everything should scale well without any issues. Remember that if you have any WindowsFormsHosts or other non-WPF components, they may not scale well. Tip: If you have a WebBrowser control with DPI scaling issues, have a look at this article.

More reading

If you'd like to read more about this, see Microsoft's documentation on WPF DPI scaling here.


This snippet is available in Codly. Click the appropriate link below to download the snippet. If you don't have Codly, it is available here in the Microsoft Store.

Did this guide help you? Do you have anything to add? Let us know in the comments! Also, if this guide did help you and you use an AdBlocker and you want to support us, consider disabling it for this site - if you do, it will be greatly appreciated!

Follow us to be notified when we release new guides:

Comments

Popular posts from this blog

How to show placeholder text in a WPF TextBox in C# and VB

How to enable dark title bar in WPF and Windows Forms/WinForms apps in C# and VB

How to use modern icons in XAML in WPF on Windows 10 and 11

How to change the colour of a WPF or Windows Forms/WinForms title bar in Windows 11 in C# and VB

Microsoft WebView2: How to check if the WebView2 runtime is installed in C# and VB