The proliferation of tablets, laptops, and monitors that provide high dots-per-inch (DPI) displays can result in Windows desktop apps that display blurry text and images. When you have devices with high-DPI displays capable of working at resolutions above 1920x1080 (also known as FullHD or 1080p), you expect both crisp text and images. In this article, the first in a two-part series, I explain the features that Windows 8.1 provides for such high-DPI displays and all the things to consider when using Win32 to deliver software containing crisp text and sharp images. In the next article, I'll take this preliminary information and turn it into the necessary code.
New High DPI Features in Windows 8.1
Windows XP introduced DPI settings in Windows along with API functions to retrieve system metrics and resolution. Windows Vista added the API functions to declare DPI awareness and the DPI virtualization of DPI unaware applications. Windows 7 enabled per user DPI settings and the automatic configuration of DPI at first logon. (When Windows desktop applications assume the default 96 DPI setting and don't take into account the system DPI settings, it is considered a "DPI unaware" application.) I'll explain how these applications work when you have high-DPI displays later.
Windows 8.1 expanded the DPI awareness features to take into account per-monitor DPI and incorporated the viewing distance in the default DPI calculation. With Windows 8.1 per-monitor DPI, a DPI aware application can scale based on the monitor DPI settings of each monitor in which it is being displayed. When you open Control Panel | Appearance and Personalization | Display, the "Let me choose one scaling level for all my displays" checkbox allows you to deactivate per-monitor scaling. When the checkbox is checked, per-monitor scaling is deactivated and the DPI settings are applied to all the displays (see Figure 1).
Figure 1: When the checkbox is checked, per-monitor scaling is deactivated on Windows 8.1 and the DPI settings are applied to all the displays. Notice that Windows 8.1 displays all the available scaling options with the percentage value.
By default, the checkbox is unchecked; if you use the slider to select a different scaling factor and then click on the Apply button, the changes will take effect immediately (see Figure 2). As you might guess, Windows will communicate the changes to the applications that have declared certain DPI awareness levels and you will have the chance to scale the elements based on the new configurations. The checkbox is checked, per-monitor scaling is deactivated on Windows 8.1 and the DPI settings are applied to all the displays. Notice that Windows 8.1 displays all the available scaling options with the percentage value.
Figure 2: The checkbox is unchecked and per-monitor scaling is activated on Windows 8.1.
A modern high DPI Windows 8.1 laptop can have a 15.6" QHD+ LED multi-touch display. In this case, the laptop delivers a 15.6" display size with 3200 horizontal pixels and 1800 vertical pixels (3200x1800). By default, the optimal scale level in Windows 8.1 for this display will be 200%. With this scale level, while the panel DPI is 235 DPI, the operating system DPI will be 192 DPI. The panel DPI is the native pixel density of the display panel. The operating system DPI (also known as OS DPI) indicates the closest match DPI that calibrates the display to a standard setting and is the setting you change in the control panel. When the scale level is set to 100%, the operating system DPI is the long-time default, 96 DPI. It's easy to see why you reach 192 DPI, as it is twice 96DPI.
When you run a DPI-unaware desktop application, Windows 8.1 uses the DPI virtualization introduced in Windows Vista to provide automatic scale support for the application with the addition of per-monitor metrics. The DPI virtualization provides virtualized system metrics and UI elements to the application as if it were running at the long-time default 96 DPI.
Windows renders the application in a sandbox at 96 DPI (100%) and the desktop window manager (also known as DWM) scales the rendered application window to match the monitor DPI setting. Considering my high-DPI laptop example, DWM will scale the DPI unaware application window from 96 DPI to 192 DPI. As a result of this scaling up based on pixel stretching, the resulting content can be blurry. Thus, instead of providing crisp and visually appealing content, the DPI-unaware application has great probability of providing a poor visual experience to the high DPI display owner on Windows 8.1.
At the time of writing this article, there is still a huge number of desktop applications that are DPI unaware and display both blurry text and images on high DPI displays with Windows 8.1. For example, Google Chrome version 35.0.1916.153 (the current version --Ed.) is a DPI-unaware application; so when you use this browser in Windows 8.1 with a high DPI display and an operating system DPI higher than 96 DPI, you will see blurry text. You can enable the "Disable display scaling on high DPI settings" checkbox included in the compatibility settings for each DPI-unaware application that has problems. However, the text and the images will probably be too small for the high resolution and the user will end up migrating to an application that provides a better visual experience for his high DPI display.
As a developer, you likely use more than one display. However, developers aren't the only users who benefit from multiple displays. If you think your desktop application might run on multiple displays, you have to understand what happens in Windows 8.1. If you launch a DPI-unaware application on the high-DPI display I used as an example and then move its window to a display with a 150% scale level, DWM will scale the application window from 96 DPI to 144 DPI.