14 msdn magazine Windows with C++
width and height of the desktop. Again, this is a logical inch and
isn’t meant to refl ect reality. Also, given these are the system DPI
values, it means they’re the same for all monitors that span the desktop
regardless of how relatively big or how small they might be. Th erein
lies the problem.
If you plug your Dell Venue 8 Pro tablet with its 8-inch screen
into an array of 30-inch Dell UltraSharp monitors, you’re going to
have to make a diffi cult choice. I routinely plug two or three vastly
diff erent monitors into my desktop’s graphics card. A system-wide
DPI scaling factor just doesn’t cut it. What’s needed is for each
monitor to have a DPI scaling factor ideally suited to its relative
size or resolution. Th is is exactly what Windows 8.1 off ers with its
per-monitor DPI scaling support.
Windows 8.1 offers up three different levels of DPI aware-
ness. This is obvious when you look at the Process Explorer
window, shown in Figure 6. You can see some applications are
completely DPI-unaware, as in the case of the command prompt.
Most applications that were written for Windows 7 and Windows
8 are system DPI-aware, or at least claim to be. Examples include
Microsoft Outlook and the calculator. Per-monitor DPI awareness
is the third and optimal level of awareness. Examples in Figure 6
include Internet Explorer and Microsoft Word. Interestingly, Word
isn’t actually per-monitor DPI-aware at the moment,
but I’ve disabled display scaling for Word to avoid blur-
riness. Th is has the eff ect of overriding the process DPI
awareness so the desktop window manager won’t scale
the window. Th is was done with a compatibility option.
Th e main point is you better make sure your apps are
per-monitor DPI-aware and scale accordingly. How
exactly can you do this? Keep reading.
Diff erent applications make various assertions about
their level of DPI awareness, and then the desktop win-
dow manager—the service responsible for composing
the various application windows together—determines
how to scale diff erent application windows based on
their individual DPI claims such that all windows are
presented at some consistent scale. If an application
claims to be per-monitor DPI-aware, the desktop win-
dow manager won’t scale the window at all and assumes
the application knows what it’s doing. If an application is system
DPI-aware, the desktop window manager will scale the window
based on the assumption that it was rendered to the system DPI
scaling factor returned by the GetDeviceCaps function I mentioned
earlier. And if an application is DPI-unaware, the desktop window
manager assumes the window was rendered to the traditional 96
DPI and scales it accordingly.
Before I consider how to actually write a well-behaving, per-
monitor, DPI-aware application, I’ll discuss what it takes to make
such a claim. Windows Vista introduced the SetProcessDPIAware
function to mark the calling process as DPI-aware. Th is function
took no arguments and simply turned on DPI awareness, so to
speak. Th is was before per-monitor awareness, so this was a sim-
ple binary state. Either you’re DPI-aware or you’re not. Windows
8.1 introduced a new function called SetProcessDpiAwareness that
provides more control over this level of awareness:
VERIFY_(S_OK, SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE));
Th is sets the process’s DPI awareness to the given level. Constants
are available to cover the three possible states: DPI-unaware,
system DPI-aware and per-monitor DPI-aware. There’s also a
corresponding GetProcessDpiAwareness function to query this
value for a given process. But using code to set the awareness
level has a number of drawbacks. You need to be careful to call
these functions early on in your application’s lifetime. Sometimes
this isn’t practical and causes a number of issues when mixing
executables and DLLs. A better solution is called for.
Figure 6 Process Explorer Showing Purported DPI Awareness
DPI Percentage
96 100
120 125
144 150
192200
Figure 4 System Scaling Factors
Resolution Scaling Options
... – 900 1 00%
900 – 1079 1 00% – 12 5%
1 080 – 1439 1 00% – 12 5% – 1 50%
144 0 – ... 1 00% – 12 5% – 1 50% – 2 00%
Figure 5 Scaling Options Relative to Vertical Resolution
I routinely plug two or three
vastly different monitors into
my desktop’s graphics card. A
system-wide DPI scaling factor
just doesn’t cut it.