Ever wonder why Windows doesn't use the actualy pixel size when you tell it to? The 96 DPI Solution.
In the never-ending quest to achieve device-independent programming
under Windows, the Windows Presentation Foundation developers have
devised a system in which all coordinates and sizes are in units of 96
dots per inch, called "device-independent units" or sometimes (rather
oxymoronically) "device-independent pixels." I will avoid the latter
term and sometime abbreviate the former as DIU. The choice
of 96 DPI (rather than, say, 72 DPI or 100 DPI) might seem arbitrary
and even perverse only to people who aren't aware that Windows by
default assumes a video display resolution of 96 DPI. (Of course, the
user can change this assumed display resolution through the Control
Panel Display applet, Settings tab, Advanced button, General tab. One
common alternative — particularly popular among users born after the
Moon landing — is 120 DPI, which generally increases fonts and other
user interface elements by 125%. I believe that 96 DPI was chosen as
the default Windows resolution rather than a rounder figure of 100 DPI
because 96 DPI is 4/3rds of the one-pixel-per-point resolution of 72
DPI.) In WPF, you always draw in units of 96 DPI. For example, if you want to create a one-inch square Rectangle
object, you make it 96 units wide and 96 units high. If the program
runs on a video display set at 96 DPI, the object will be drawn 96
pixels square. In the most common case device-independent units map
directly to pixels. If the program runs on a video display set at 120
DPI, the object will be drawn as 120 pixels square. That's a fairly
clean 3 units-to-4 pixels mapping. These device-independent
units aren't restricted to graphics programming. They pervade the
entire WPF. You use device-independent units to specify sizes of
controls, for example. You get mouse coordinates in terms of
device-independent units. Device-independent units even show up in
system parameters. The beauty of the system is that everything is
consistent. It's not like a mapping mode where you have to convert
between mouse coordinates in pixels and whatever graphics units you
happen to have set. It's an entire consistent world out of which you
really can't escape. The pervasiveness of this coordinate
system takes some getting used to. Here, for example, are the values of
three static properties of the SystemParameters class obtained under four different Windows sessions with the display resolution set as shown in the column headings: Property | 72 DPI | 96 DPI | 120 DPI | 144 DPI | SystemParameters.PrimaryScreenWidth/Height | 1866-2/3 x 1400 | 1400 x 1050 | 1120 x 840 | 933-1/3 x 700 | SystemParameters.IconWidth/Height | 42-2/3 | 32 | 25.6 | 21-1/3 | SystemParameters.CaptionWidth/Height | 25-1/3 | 25 | 24.8 | 25-1/3 |
The video display on which I ran the little program that interrogated
these properties is actually 1400 by 1050 pixels. When the Windows
display resolution is set to 96 DPI, that's exactly what's reported.
That pixel size and resolution implies a metrical size of about 14.6
inches by 10.9 inches. The dimensions of the video display in
device-independent units is reported as something different when other
display resolutions are set, but the metrical size remains the same.
Icons displayed on the desktop are 32 pixels square regardless of the
display resolution. If you have Windows set for 96 DPI, the icon size
is reported as 32 device-independent units. As the assumed display
resolution goes up, the size of the icons in device-independent units
goes down proportionally. Windows uses a different pixel
size of buttons displayed on the caption bar depending on the display
resolution. The idea is that the buttons should always have about the
same relationship to the default font. In device-independent units,
therefore the button size is roughly the same regardless of display
resolution, and is always approximately 1/4 inch. It's not exactly
the same across display resolutions because these buttons always have
an integral pixel size. For example, at a display resolution of 144
DPI, the pixel size is 38, which (multiplied by 2/3) is a DIU size of
25-1/3. For 120 DPI, the pixel size is 31, which (when multiplied by
0.8) is the DIU size of 24.8. For 72 DPI, the pixel size is 19.
Multiply by 4/3 for the DIU size of 25-1/3. I was recently
working on a little calculator program where I made square buttons by
simply giving them a dimension of 32 by 32 device-independent units.
That's 1/3 inch regardless of display resolution, and a comfortable
size to accomodate text in the default font. Where I haven't
quite grown accustomed to device-independent units is in specifying
font sizes. Font sizes are specified in units of 96 DPI as well, so if
you want a 24-point font, you need to increase the point size by 1/3
and specify a FontSize property of 32. Every time I do that, I
think that WPF should have used a device-independent coordinate system
based on 72 DPI rather than 96 DPI. Of course, a 72 DPI coordinate
system has been done before in other graphical environments, but
there's no shame in that. It's not quite clear how this will work with printing. In the November CTP of WPF that we're all running, the entire System.Printing namespace hasn't even a tiny morsel of documentation. By Charles Petzold. [Charles Petzold]
12:39:59 PM
|