A number of factors are driving the requirement for applications to correctly support high DPI settings--increased monitor resolutions are making it more difficult for users to read text on the screen, compliance with disability access legislation is an increasingly important factor for corporations, and users are now expecting applications to behave well at higher DPI settings. MFC 10 and Visual C++ 2010 have built-in support for high DPI, making the development of a DPI-aware application quicker and more simple.
For developers with huge multi-monitor setups, problems with the text displayed on the screen being too small to read is rarely a problem. For end-users that have a 13" full-HD laptop or a 9" net-book, the readability of text in a 9-point font during the morning commute or a business flight is a different matter, and the traditional solution has been to lower the resolution of Windows so the text becomes more readable. The problem with this solution is that the crispness of display is compromised by running Windows at a resolution not natively supported by the monitor.
Microsoft is focusing very heavily on delivering an outstanding user experience to combat the threat of Apple, and a component of this focus is alleviating problem like a fuzzy display caused by low monitor resolution. The key element in allowing users to run at the native resolution of a monitor while keeping text readable is applications providing support for high DPI text values. The default dots per inch (DPI) that Windows renders text at is 96. By launching the Display Control Panel Applet (Control Panel\Appearance and Personalization\Display) on Windows 7 (as shown in Figure 1) the text DPI can be increased.
Figure 1. Changing DPI on Windows 7
The monitor that this screen shot was captured on is a laptop with a small maximum resolution (1280 by 800), so the only DPI offered is a 125% increase, which takes the text to 120 DPI. Higher DPI values including 150% (144 DPI) and 200% (192 DPI) can be achieved by selecting the Set custom text size (DPI) link at the bottom left of Figure 1, which brings up the dialog shown in Figure 2.
Figure 2. Custom DPI settings on Windows 7
The screen captures below show the effect of the various DPI settings. Figure 3 is the Windows Start menu at the standard DPI of 96 (Figure 3), 120 DPI (Figure 4) and 144 DPI (Figure 5). Notice that despite the increases in text size, the menu remains crisp and clear as the display is still using the native resolution of the target monitor.
Figure 3. Windows Start Menu at 96DPI
Figure 4. Windows Start Menu at 120DPI
Figure 5. Windows Start Menu at 144DPI
The trouble with high DPI settings is that a lot of applications don't render correctly. Figure 6 shows the VLC media player Open Media dialog at 144DPI, and it is apparent that the Device Selection buttons have covered the Video Device Name label and the text of the Advanced options button is too large to fit on the button. This is a common problem for applications running at higher DPI settings. This has often resulted in users abandoning high DPI and dealing with a fuzzy screen display with lower display resolution.
Figure 6. Typical High DPI Problems
Windows Vista and above supports a high DPI virtualization mode to address the problems like those evident in Figure 6. With this DPI virtualization, Windows essentially runs the individual applications at a smaller screen resolution by 'tricking' the application with virtualized screen dimension. For example, if an application has a 500 by 500 pixel dialog with a 100 pixel text box at the standard DPI setting, the dialog would run at 750 by 750 pixels with a 150 pixel text box at 144DPI with virtualization. While this solves the text clipping problem, the crisp display of the application is compromised as shown in Figure 7.
Figure 7. DPI Virtualization - No Text Clipping But Display Crispness is Lost
For applications that have been developed with support for higher DPI settings, virtualization is not required and would actually detract from the applications display. To let Windows know that DPI virtualization is not required for an application, an application's manifest file needs to explicitly opt-out of virtualization. The XML snippet below shows the required manifest file setting required to achieve this.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<ms_windowsSettings:dpiAware xmlns:ms_windowsSettings="http://schemas.microsoft.com/SMI/2005/WindowsSettings" xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
For Visual C++ applications, the Configuration Properties of the application can be used to setup the manifest file for DPI awareness. The specific setting required is Enable DPI Awareness on the Manifest Tool | Input and Output setting page as shown in Figure 8.
Figure 8. Configuring DPI Awareness for a MFC Application
MFC generally does a very good job in automatically handling the scaling of controls to support the larger area required for high-DPI text. Figures 9 through 11 show the same MFC dialog at 96, 120 and 144 DPI. Despite the crowded nature of the dialog at 96 DPI, the increases in text size at 120 and 144 DPI have resulted in a larger dialog rather than text clipping. For MFC applications that use the standard MFC controls without advanced tweaks and optimizations, the automatic resizing of controls will result in higher DPI support without custom coding.
Figure 9. Tightly-spaced MFC Dialog at 96 DPI
Figure 10. Tightly-spaced MFC Dialog at 120 DPI
Figure 11. Tightly-spaced MFC Dialog at 144 DPI
The two areas where custom DPI code can be required is with owner-drawn controls and bitmaps. The problem with bitmaps is obvious--if the 160 by 87 pixel dialog shown in Figure 9 had a similarly sized bitmapped background, the same sized bitmapped will not displayed correctly in the 238 by 126 pixel dialog that will be produced at 144 DPI. As Windows allows users to select any custom DPI setting (the ruler in Figure 2 can be dragged left and right to achieve any DPI setting up to 192 DPI), the most robust way to render a bitmap is to simply detect the size of the parent control at runtime and scale accordingly. This approach may result in a loss of crispness, especially if the bitmap contains text or sharply-defined lines at its native resolution.
Custom-drawn controls also need to be DPI aware. MFC and Windows provide rich functionality for converting logical units into the actual pixels that will be required on the screen when the graphical output is rendered. By producing clean, robust code that calls MFC functions like CDC::GetTextExtent to determine the output size of a string rather than just visually judging at runtime, correct rendering at any DPI setting will be achieved. As well as the DPI-awareness benefits, the application will also be easier to internationalize, with different controls sizes based on the varying string length of text in different languages being accommodated.
Visual C++ 2010
and MFC 10
go a long way to supporting high DPI awareness out-of-the-box. The default manifest file settings for a Visual C++ 2010 application
will result in clear, crisp display at higher DPI settings, and MFC dialogs will generally increase in size when Windows has higher DPI settings active. For applications produced for a wide audience, supporting accessibility features like high DPI is a key selling point, and testing a Windows application at various DPI settings is of the same importance as testing the display of a website in various browsers. The legislative requirements for computer accessibility, and enforcement of this legislation, is increasingly important for companies that produce software, and the simple techniques for achieving DPI awareness in MFC
make producing compliant applications an achievable and worthwhile undertaking.