High DPI Settings in Windows

Windows Vista and later offer two mechanisms to accommodate monitors with a high pixel density (dots per inch, DPI): enlarged system fonts and whole-window bitmap scaling. Unfortunately, trying to make all your applications work with either setting can be aggravating, thanks to a combination of lazy developers and bad decisions made by Microsoft. This page is intended to help users of high DPI settings understand and fix those problems.

Scaling Methods

Traditionally, native Windows desktop applications rely on two mechanisms to draw on the screen:

  • Call functions in the Graphics Device Interface (GDI) API to address the display. Usually, GDI coordinates map directly to screen pixels, regardless of monitor size and pixel density.
  • Use Windows system fonts to draw text. This is optional, but most desktop applications use system fonts for most of their graphical user interface (GUI).

In the old days, practically every monitor had the same pixel density of about 96 DPI, so application GUIs drawn in this way looked roughly the same on every system. But as pixel densities increased, application GUIs shrank in terms of centimeters or inches. Small text and other fine details became increasingly harder to see.

Microsoft therefore thought it would be a good idea to build some kind of display scaling into Windows. Both of the following methods are triggered by the user selecting a custom DPI setting that is higher than the standard 96 DPI, and both methods attempt to scale up the size of display elements accordingly.

Windows XP Style DPI Scaling

The first of these methods dates back to Windows XP and is therefore known as Windows XP style DPI scaling. This method does not actually scale an application GUI as such. Only the system fonts and other system UI elements are enlarged at higher DPI settings.

Otherwise, applications still draw their GUIs with a 1:1 correspondence of specified GDI coordinates to visible screen pixels. The only difference in their visual appearance is that any text drawn using system fonts is suddenly bigger, e.g. text labels on buttons. This causes obvious problems which we’ll get to in a minute.

Windows Vista DPI Virtualization

Windows Vista introduced a second option, rather lamely called “display scaling” with no further qualification, so as to maximize user confusion. We’ll use the more descriptive internal name: DPI virtualization. When this option is enabled, Windows still performs XP style scaling. Just as before, the sizes of all system fonts and system UI elements are increased.

The difference is that applications which can handle high DPI settings are now expected to inform Windows of this fact. Such applications must set a new “DPI-aware” flag, either by calling the Win32 API function SetProcessDPIAware (not recommended) or by embedding an application manifest with the flag dpiAware. If that flag is missing, Windows first renders the entire application window to an internal bitmap using 96 DPI sizes, and then scales up that bitmap to the current DPI setting before putting it on the screen.

This would be a fantastic scaling method if all our monitors had the pixel density of the latest iPhones (326 DPI). Unfortunately they don’t, and application windows scaled up in this fashion look annoyingly blurry at the common pixel density of 120 DPI. Microsoft therefore disables DPI virtualization by default, unless you choose a pixel density greater than 120 DPI.

Further Reading

For more information about both scaling methods, especially from a developer perspective, please read the MSDN article Writing High-DPI Win32 Applications. This article also contains a sample manifest to declare an application as DPI-aware, as well as sample screenshots for the various scaling methods and tips on display scaling in native code.

Changing DPI Settings

On Windows 7, open the Control Panel, then choose “Appearance and Personalization”, then “Display”, and finally select “Set custom text size (DPI)” from the list on the left. You will see the following dialog:

The drop-down box at the top lets you enter the desired DPI setting as a percentage value, where 100% equals 96 DPI. The 125% in the screenshot therefore equals 120 DPI. The check box outlined in red at the bottom determines whether to use Windows XP style DPI scaling or Windows Vista’s new DPI virtualization. If it is unchecked, as in the screenshot, then DPI virtualization is enabled.

Rant. This dialog is a usability trainwreck. The check box seems to disable XP style scaling. But that scaling method (which only enlarges system fonts and other system UI elements) is effectively always enabled when you run at high DPI. What the check box actually controls is the exclusive use of this method, versus the additional use of DPI virtualization for applications that lack the DPI-aware flag. So the check box doesn’t control the scaling method stated in its label, but a different scaling method not mentioned anywhere – and it enables that method when it is unchecked!

Help, my system fonts are the wrong size!

Sometimes, after changing DPI settings, you may notice certain system fonts that are either too big or too small for your new settings. The likely cause is that you were using a custom desktop theme based on your old DPI settings, and Windows does not dare scale the fonts of custom themes.

If you actually did create a custom desktop theme and want to retain it, you’ll have to edit the fonts yourself to adapt them to your new DPI settings. However, Windows has an annoying habit of “helpfully” creating custom themes all by itself, for whatever reason. So if you never wanted a custom desktop theme to begin with, delete it and revert to a standard theme.

On Windows 7, open the Control Panel, choose “Appearance and Personalization” and then “Personalization”. If you see a selected entry in the “My Themes” row at the top, that means Windows is using a custom theme which is messing with your system font scaling. Select a standard theme instead, e.g. the first entry under “Aero Themes”, and delete the unwanted “My Themes” entry. All system fonts should now appear correctly.

Application Types

Now let’s see how existing Windows applications deal with high DPI settings (or not).

  • Applications with no DPI awareness at all. — These are either very old or very poorly written, but nonetheless still disturbingly common. One notorious example is Apple’s iTunes for Windows. Here lazy developers use system fonts in their GUI, but rather than querying Windows for the actual font sizes they simply hardcode the 96 DPI sizes into their window layout, naturally screwing up the GUI when higher DPI settings increase those sizes. Such applications require the new DPI virtualization, fuzziness be damned; otherwise you’ll encounter problems ranging from cut-off text to overlapping controls, sometimes making the GUI entirely unusable (although that is fortunately rare).
  • Applications with DPI awareness but no DPI-aware flag. — These are typical XP-era applications. Here the developers take care to obtain the actual system font sizes before constructing their GUI. Such applications display correctly under XP style scaling. Unfortunately, since they don’t set the proper flag to inform Windows of this fact, DPI virtualization will default them to fuzzy bitmap scaling. That is both unnecessary and undesirable.
  • Applications with DPI awareness and DPI-aware flag. — These are the newest type of applications, and the only one that’s entirely unproblematic regardless of your DPI settings. The DPI-aware flag is set automatically for Windows Presentation Foundation (WPF) and GDI+ applications, as these APIs provide built-in layout scaling. Developers using the old GDI API need to manually flag their DPI-aware applications.

Choosing a Scaling Method

Once you have decided that you want to use a high DPI setting, your choice of scaling method depends on the applications you’re running. Keep in mind that disabling DPI virtualization means enabling “Windows XP style DPI scaling” using the poorly-worded check box, and vice versa.

  • If you are so incredibly lucky as to use only applications that are both DPI-aware and set the required flag, it doesn’t matter which scaling method you choose. All applications will use XP style scaling, and DPI virtualization will never get used.
  • If you use only well-written applications that are DPI-aware, but some of them don’t set the required flag, you should disable DPI virtualization. That way all applications will display correctly, without any blurry bitmap scaling. If your monitor has a really high pixel density so that scaled bitmaps no longer look blurry, you might want to enable DPI virtualization anyway.
  • If you do have one or more poorly-written application without any DPI awareness, you must enable DPI virtualization unless you’re willing to tolerate the application’s screwed-up GUI. Unfortunately, this results in a secondary problem because Microsoft designed this option the wrong way around. DPI virtualization is opt-out rather than opt-in: you can only enable it for the entire system, then you must selectively disable it for individual applications.

Opting Out of DPI Virtualization

Once you have decided to enable DPI virtualization, you must now scour your system for any DPI-aware applications that lack the corresponding flag, and opt them out of fuzzy bitmap scaling. This reverts them to the XP style scaling they were designed for. There are two ways to do this, one that works only for 32-bit applications and one that also works for 64-bit applications.

  • 32-bit Applications. — This is simple: right-click on the executable in Windows Explorer, select the “Properties” dialog, switch to the “Compatibility” tab, and check the option “Disable display scaling on high DPI settings”. That’s all!
  • 64-bit Applications. — For no apparent reason other than to annoy 64-bit users, Microsoft disabled the above check box for 64-bit applications, even though the option itself is perfectly functional when set directly in the registry! So you must do the following: start up Registry Editor, navigate to the key HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers, and add a string value (REG_SZ) whose name is the full path to the application executable and whose value is HIGHDPIAWARE. I recommend that you first modify a few 32-bit applications as described above, so you can see some example values in this registry key.

So that’s how to use high DPI settings on Windows Vista and later. And if you have ever wondered what the compatibility option “Disable display scaling on high DPI settings” is for, and why it didn’t do anything on your system, now you know: it’s only effective if you have enabled system-wide DPI virtualization, and then only for applications that are bitmap-scaled because they don’t set the DPI-aware flag.