Common Problems Related to DPI Adjustments
Instead of making the DWM scale your applications, you can indicate to DWM that you will take care of scaling your application. However, before I explore the different paths you can chose to make your application scale, you should consider the following list of the most common problems you might face when the application needs to scale, and how you can prepare your application to avoid these problems.
- Blurry text. When applications don't scale, you can use bitmap fonts that look good at a specific size. However, when your application has to scale the text, bitmap fonts will cause blurry or pixelated text. Thus, you should avoid using bitmap fonts. You should use either TrueType or OpenType fonts because they will appropriately scale their size, there by displaying crisp text.
- Blurry images. If you scale up bitmapped graphics such as button icons, you don't take full advantage of all the available pixels to provide crisp images and they will appear pixelated. If you decide to use higher-resolution images and scale them down, you will lose detail. The application will provide the best visual experience if you prepare multiple versions of each bitmap graphic asset to make them match certain preset DPI settings. I'll cover this topic in more detail later.
- Clipped text and/or clipped UI elements. This problem occurs when some elements are resized but others aren't. For example, the text for a button is resized but its container button isn't. When the application scales, it must resize completely in response to the new system metrics. When the application doesn't scale all the UI elements, the UI layout can make it difficult or even impossible for the user to interact with the different elements.
- Inconsistent font sizes. When you use the wrong font APIs, the text that uses these fonts doesn't resize dynamically in response to the changes in the DPI settings. If you use the appropriate font APIs, you will be able to work in a DPI-independent way.
- Incorrect input management. When the application makes a wrong alignment of the coordinate space with the DPI settings, it will affect input. This problem generates controls that don't respond to mouse or touch input, failures to perform drag-and-drop operations, and touch gestures that don't work as expected.
- Extremely thin lines. If you don't scale the line width, lines can be extremely thin and almost invisible at higher DPI settings.
To achieve the best results, you must plan how to scale your content and prepare specific bitmap graphics for the different DPI settings. The following list shows the five most common DPI settings that Windows 8.1 makes available to the user in the Control Panel settings. However, not all the options are available for all displays.
- 96 DPI. Smaller - 100%
- 120 DPI. Medium - 125%
- 144 DPI. Larger - 150%
- 192 DPI. Extra Large - 200%
- 240 DPI. Extra Extra Large - 250%
Thus, if you want your application to provide the best bitmap graphics for any DPI setting, you will need to prepare 5 sets of images. Of course, in some cases, scaling will work OK; but in other cases, it makes sense to prepare the different sets. Icons are the best example of the bitmap graphics that benefit from multiple versions: one for each DPI setting. Obviously, you can provide a reduced set of bitmap graphics (just two or three instead of five) and scale the images with the nearest DPI. For example, you can provide 96, 120, and 144 DPI sets. If the monitor has a 192 DPI setting, you can scale up the 144 DPI bitmap graphics. The results are going to be clearer than with a 96 DPI bitmap graphic scaled up to 192 DPI. In the first case, you just scale 133%; but in the second case, you need to scale 200%, which will result in a very blurry image.
If you want to provide the best visual experience for an application that has to display icons that have a 32x32 resolution in the baseline 96 DPI setting, create icons with the following sizes to target each DPI setting:
- 96 DPI: 32x32
- 120 DPI: 40x40
- 144 DPI: 48x48
- 192 DPI: 64x64
- 240 DPI: 80x80
As I explained previously, Windows 8.1 determines a default operating system DPI or optimal scale level for each monitor based on multiple factors, such as the panel DPI, the display size, the vertical resolution, and the viewing distance. While the optimal scale for a 15.6" QHD+ display is 200% (192 DPI), the optimal scale for a 13.3" QHD+ display is 250% (240 DPI). The 13.3" panel has the same resolution than the 15.6" panel (3200x1800), but the smaller display size increases the 13.3" panel DPI and 240 DPI is a more suitable OS DPI for this panel.
Considering that 3840x2160 displays (also known as 4K, QFHD, Ultra HD, UHD, or 2160p) are already available in laptops and monitors, a pleasant visual experience with high DPI displays can be a good long-term investment for your desktop applications.
The DPI setting for the monitor causes another common problem the change in the effective resolution. Consider the 13.3" display that offers a 3200x1800 resolution and is configured with an OS DPI of 240 DPI. The high DPI setting makes the system use both larger fonts and UI elements; therefore, the elements consume more pixels to render than the same elements displayed in the resolution configured with an OS DPI of 96 DPI. The effective resolution of a display that provides 3200x1800 pixels configured at 240 DPI is 1280x720. The effective resolution can become a big problem because an application that requires a minimum resolution of the old standard 1024x768 pixels with an OS DPI of 96 DPI would have problems with a 3200x1800 pixels display configured at 240 DPI, and it wouldn't be possible to display all the necessary UI elements. It may sound crazy, but the effective vertical resolution is 720 pixels, lower than the 768 vertical pixels required by the application to display all the UI elements without problems.
The formula to calculate the effective resolution is simple: Divide the physical pixels by the scale factor (OS DPI / 96). For example, the following formula calculates the horizontal effective resolution of my previous example: 3200 / (240 / 96) = 3200 / 2.5 = 1280; and the following formula calculates the vertical effective resolution: 1800 / (240 / 96) = 1800 / 2.5 = 720.
The effective resolution would be of 1800x900 pixels if the same physical resolution were configured at 192 DPI. Effective horizontal resolution: 3200 / (192 / 96) = 3200 / 2 = 1600; and vertical effective resolution: 1800 / (192 / 96) = 1800 / 2 = 900. Windows 8.1 considers the physical resolution height to disable certain DPI scale options in order to make sure that the effective resolution isn't lower than the minimum required for the operating system.
Different DPI Aware Options in Window 8.1
If you want to take full advantage of high-DPI displays to provide clearer and more detailed content in your Win32 desktop applications, you can declare your application as either of the following:
- System DPI aware
- Per-monitor DPI aware
A system DPI-aware application takes into account the system DPI configuration and tells DWM that it will make all the necessary adjustments and scale the content based on this setting and will make its best efforts to render with clear and detailed content in the primary display. However, a system DPI-aware application doesn't respond to dynamic changes in DPI settings in a single session. If the user moves the system DPI-aware application window to a different display with a different DPI setting, DWM will scale the content up or down based on the DPI settings difference. As a result, if the user has displays with different DPI settings, your system DPI-aware application might be blurry in the secondary display.
A per-monitor DPI aware application always renders at the DPI setting for each display in which it is being displayed. The application dynamically scales up or down when the user changes DPI settings or moves the application window to a different display with a different DPI setting. DWM never scales per-monitor DPI aware applications, so they always render clear, crisp, and detailed content. The application has to figure out the right scale factor, listen for changes in DPI settings, recalculate, and render again the layout.
As you can see, a per-monitor DPI aware application requires an additional development investment compared with a system-DPI aware application. However, if you want to provide the best visual experience for users who might work with multiple displays, per-monitor DPI-aware is the best option.
In the next article, I'll provide a complete example of both a system-DPI application and a per-monitor DPI-aware application. This way, you will see the different configurations for your application based on the selected mode, and understand the changes in the code required to convert a system-DPI application to per-monitor DPI-aware.
Gastón Hillar is a senior contributing editor at Dr. Dobb's.