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.
See DPI Scaling in Windows GUIs for an evaluation of popular GUI frameworks with regard to DPI scaling. Check out Andrew McKinlay’s The Joys of High DPI for a nice (and terrifying) war story on working with high DPI in Windows 7.
Traditionally, native Windows desktop applications rely on two mechanisms to draw on the screen:
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.
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 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.
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.
On Windows 7/8, open the Control Panel, then choose “Appearance and Personalization”, then “Display”, and finally select “Set custom text size (DPI)” (Windows 7) or “Custom sizing options” (Windows 8). You will see the following dialog (Windows 7 screenshot, Windows 8 is nearly identical):
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. You can also put a ruler to your screen and attempt to match its markings by dragging the displayed ruler. 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!
Windows 8 Bug. In addition to being incomprehensible, this dialog also appears to be buggy in Windows 8. Generally everything works as in Windows 7, but the state of the check box doesn’t stick. When you check it and confirm, DPI virtualization is correctly disabled and stays that way. However, the check box itself will appear unchecked again the next time you open this dialog.
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. 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/8, 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” (Windows 7) or “Windows Default Themes” (Windows 8), and delete the unwanted “My Themes” entry. All system fonts should now appear correctly.
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). See my weblog article for sample screenshots of broken applications.
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 — This is 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.
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” and vice versa, using the poorly-worded check box.
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’ll have to start up Registry Editor and navigate to this key:
Now 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.