Logo
PREGNANCY
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
 
 
Windows XP

Windows Presentation Foundation in .NET 4 : Introducing WPF - Resolution Independence

8/15/2011 6:23:51 PM
Traditional Windows applications are bound by certain assumptions about resolution. Developers usually assume a standard monitor resolution (such as 1024 by 768 pixels), design their windows with that in mind, and try to ensure reasonable resizing behavior for smaller and larger dimensions.

The problem is that the user interface in traditional Windows applications isn't scalable. As a result, if you use a high monitor resolution that crams pixels in more densely, your application windows become smaller and more difficult to read. This is particularly a problem with newer monitors that have high pixel densities and run at correspondingly high resolutions. For example, it's common to find consumer monitors (particularly on laptops) that have pixel densities of 120 dpi or 144 dpi (dots per inch), rather than the more traditional 96 dpi. At their native resolution, these displays pack the pixels in much more tightly, creating eye-squintingly small controls and text.

Ideally, applications would use higher pixel densities to show more detail. For example, a high-resolution monitor could display similarly sized toolbar icons but use the extra pixels to render sharper graphics. That way, you could keep the same basic layout but offer increased clarity and detail. For a variety of reasons, this solution hasn't been possible in the past. Although you can resize graphical content that's drawn with GDI/GDI+, User32 (which generates the visuals for common controls) doesn't support true scaling.

WPF doesn't suffer from this problem because it renders all user interface elements itself, from simple shapes to common controls such as buttons. As a result, if you create a button that's 1 inch wide on your computer monitor, it can remain 1 inch wide on a high-resolution monitor—WPF will simply render it in greater detail and with more pixels.

This is the big picture, but it glosses over a few details. Most importantly, you need to realize that WPF bases its scaling on the system DPI setting, not the DPI of your physical display device. This makes perfect sense—after all, if you're displaying your application on a 100-inch projector, you're probably standing several feet back and expecting to see a jumbo-size version of your windows. You don't want WPF to suddenly scale down your application to "normal" size. Similarly, if you're using a laptop with a high-resolution display, you probably expect to have slightly smaller windows—it's the price you pay to fit all your information onto a smaller screen. Furthermore, different users have different preferences. Some want richer detail, while others prefer to cram in more content.

So, how does WPF determine how big an application window should be? The short answer is that WPF uses the system DPI setting when it calculates sizes. But to understand how this really works, it helps to take a closer look at the WPF measurement system.

1. WPF Units

A WPF window and all the elements inside it are measured using device-independent units. A single device-independent unit is defined as 1/96 of an inch. To understand what this means in practice, you'll need to consider an example.

Imagine that you create a small button in WPF that's 96 by 96 units in size. If you're using the standard Windows DPI setting (96 dpi), each device-independent unit corresponds to one real, physical pixel. That's because WPF uses this calculation:

[Physical Unit Size] = [Device-Independent Unit Size] × [System DPI]
= 1/96 inch × 96 dpi
= 1 pixel

Essentially, WPF assumes it takes 96 pixels to make an inch because Windows tells it that through the system DPI setting. However, the reality depends on your display device.

For example, consider a 19-inch LCD monitor with a maximum resolution of 1600 by 1200 pixels. Using a dash of Pythagoras, you can calculate the pixel density for this monitor, as shown here:



In this case, the pixel density works out to 100 dpi, which is slightly higher than what Windows assumes. As a result, on this monitor a 96-by-96-pixel button will be slightly smaller than 1 inch.

On the other hand, consider a 15-inch LCD monitor with a resolution of 1024 by 768. Here, the pixel density drops to about 85 dpi, so the 96-by-96 pixel button appears slightly larger than 1 inch.

In both these cases, if you reduce the screen size (say, by switching to 800 by 600 resolution), the button (and every other screen element) will appear proportionately larger. That's because the system DPI setting remains at 96 dpi. In other words, Windows continues to assume it takes 96 pixels to make an inch, even though at a lower resolution it takes far fewer pixels.

As you no doubt know, LCD monitors are designed to work best at a specific resolution, which is called the native resolution. If you lower the resolution, the monitor must use interpolation to fill in the extra pixels, which can cause blurriness. To get the best display, it's always best to use the native resolution. If you want larger windows, buttons, and text, consider modifying the system DPI setting instead (as described next).


2. System DPI

So far, the WPF button example works exactly the same as any other user interface element in any other type of Windows application. The difference is the result if you change the system DPI setting. In the previous generation of Windows, this feature was sometimes called large fonts. That's because the system DPI affects the system font size but often leaves other details unchanged.

NOTE

Many Windows applications don't fully support higher DPI settings. At worst, increasing the system DPI can result in windows that have some content that's scaled up and other content that isn't, which can lead to obscured content and even unusable windows.

This is where WPF is different. WPF respects the system DPI setting natively and effortlessly. For example, if you change the system DPI setting to 120 dpi (a common choice for users of large high-resolution screens), WPF assumes that it needs 120 pixels to fill an inch of space. WPF uses the following calculation to figure out how it should translate its logical units to physical device pixels:

[Physical Unit Size] = [Device-Independent Unit Size] × [System DPI]
= 1/96 inch × 120 dpi
= 1.25 pixels

In other words, when you set the system DPI to 120 dpi, the WPF rendering engine assumes one device-independent unit equals 1.25 pixels. If you show a 96-by-96 button, the physical size will actually be 120 by 120 pixels (because 96 × 1.25 = 120). This is the result you expect—a button that's 1 inch on a standard monitor remains 1 inch in size on a monitor with a higher pixel density.

This automatic scaling wouldn't help much if it applied only to buttons. But WPF uses device-independent units for everything it displays, including shapes, controls, text, and any other ingredient you put in a window. As a result, you can change the system DPI to whatever you want, and WPF will adjust the size of your application seamlessly.

NOTE

Depending on the system DPI, the calculated pixel size may be a fractional value. You might assume that WPF simply rounds off your measurements to the nearest pixel. However, by default, WPF does something different. If an edge of an element falls between pixels, it uses anti-aliasing to blend that edge into the adjacent pixels. This might seem like an odd choice, but it actually makes a fair bit of sense. Your controls won't necessarily have straight, clearly defined edges if you use custom-drawn graphics to skin them; so some level of anti-aliasing is already necessary.

The steps for adjusting the system DPI depend on the operating system. The following sections explain what to do, depending on your operating system.

2.1. Windows XP
  1. Right-click your desktop and choose Display.

  2. Choose the Settings tab and click Advanced.

  3. On the General tab, choose Normal Size (96 dpi) or Large Size (120 dpi). These are the two recommended options for Windows XP, because custom DPI settings are less likely to be supported by older programs. To try a custom DPI setting, choose Custom Setting. You can then specify a specific percentage value. (For example, 175% scales the standard 96 dpi to 168 dpi.)

2.2. Windows Vista
  1. Right-click your desktop and choose Personalize.

  2. In the list of links on the left, choose Adjust Font Size (DPI).

  3. Choose between 96 or 120 dpi. Or click Custom DPI to use a custom DPI setting. You can then specify a percentage value, as shown in Figure 1. (For example, 175% scales the standard 96 dpi to 168 dpi.) In addition, when using a custom DPI setting, you have an option named Use Windows XP Style DPI Scaling, which is described in the sidebar "DPI Scaling with Windows Vista and Windows 7."

Figure 1. Changing the system DPI

2.3. Windows 7
  1. Right-click your desktop and choose Personalize.

  2. In the list of links at the bottom-left of the window, choose Display.

  3. Choose between Smaller (the default option), Medium, or Larger. Although these options are described by scaling percentages (100%, 125%, or 150%), they actually correspond to the DPI values 96, 120, and 144. You'll notice that the first two are the same standards found in Windows Vista and Windows XP, while the third one is larger still. Alternatively, you can click Set Custom Text Size to use a custom DPI percentage, as shown in Figure 1-1. (For example, 175% scales the standard 96 dpi to 168 dpi.) When using a custom DPI setting, you have an option named Use Windows XP Style DPI Scaling, which is described in the sidebar "DPI Scaling with Windows Vista and Windows 7."

DPI Scaling with Windows Vista and Windows 7

Because older applications are notoriously lacking in their support for high DPI settings, Windows Vista introduced a new technique called bitmap scaling. Windows 7 also supports this feature.

With bitmap scaling, when you run an application that doesn't appear to support high DPI settings, Windows resizes it as though it were an image. The advantage of this approach is that the application still believes it's running at the standard 96 dpi. Windows seamlessly translates input (such as mouse clicks) and routes them to the right place in the application's "real" coordinate system.

The scaling algorithm that Windows uses is a fairly good one—it respects pixel boundaries to avoid blurry edges and uses the video card hardware where possible to increase speed—but it inevitably leads to a fuzzier display. It also has a serious limitation in that Windows can't recognize older applications that do support high DPI settings. That's because applications need to include a manifest or call SetProcessDPIAware (in User32) to advertise their high DPI support. Although WPF applications handle this step correctly, applications created prior to Windows Vista won't use either approach and will be stuck with bitmap scaling even when they support higher DPIs.

There are two possible solutions. If you have a few specific applications that support high DPI settings but don't indicate it, you can configure that detail manually. To do so, right-click the shortcut that starts the application (in the Start menu) and choose Properties. On the Compatibility tab, enable the option named Disable Display Scaling on High DPI Settings. If you have a lot of applications to configure, this gets tiring fast.

The other possible solution is to disable bitmap scaling altogether. To do so, choose the Use Windows XP Style DPI Scaling option in the Custom DPI Setting dialog box shown in Figure 1-1. The only limitation of this approach is that there may be some applications that won't display properly (and possibly won't be usable) at high DPI settings. By default, Use Windows XP Style DPI Scaling is checked for DPI sizes of 120 or less but unchecked for DPI sizes that are greater.


3. Bitmap and Vector Graphics

When you work with ordinary controls, you can take WPF's resolution independence for granted. WPF takes care of making sure that everything has the right size automatically. However, if you plan to incorporate images into your application, you can't be quite as casual. For example, in traditional Windows applications, developers use tiny bitmaps for toolbar commands. In a WPF application, this approach is not ideal because the bitmap may display artifacts (becoming blurry) as it's scaled up or down according to the system DPI. Instead, when designing a WPF user interface, even the smallest icon is generally implemented as a vector graphic. Vector graphics are defined as a set of shapes, and as such they can be easily scaled to any size.

NOTE

Of course, drawing a vector graphic takes more time than painting a basic bitmap, but WPF includes optimizations that are designed to lessen the overhead to ensure that drawing performance is always reasonable.

It's difficult to overestimate the importance of resolution independence. At first glance, it seems like a straightforward, elegant solution to a time-honored problem (which it is). However, in order to design interfaces that are fully scalable, developers need to embrace a new way of thinking.

Other -----------------
- Windows Presentation Foundation in .NET 4 : Introducing WPF - The Evolution of Windows Graphics & A Higher-Level API
- Silverlight and ASP.NET : WCF Services and Silverlight
- Silverlight and ASP.NET : Integrating with HTML & Animations
- Silverlight and ASP.NET : Silverlight and Layout
- Silverlight and ASP.NET : Adding Silverlight Content to a Web Page
- Silverlight and ASP.NET : XAML
- Silverlight and ASP.NET : Creating a Silverlight Application
- Microsoft ASP.NET 4 : Developing a Web Part
- Microsoft ASP.NET 4 : The Web Parts Architecture
- Microsoft ASP.NET 4 : Handlers and Session State & Generic Handlers (ASHX Files)
- Microsoft ASP.NET 4 : HTTP Handlers - Handlers and IHttpHandler
- Microsoft ASP.NET 4 : HTTP Handlers - The Built-in Handlers
- Microsoft ASP.NET 4 : ASP.NET Request Handlers
- Microsoft ASP.NET 4 : HttpModules (part 2) - Seeing Active Modules & Storing State in Modules
- Microsoft ASP.NET 4 : HttpModules (part 1) - Existing Modules & Implementing a Module
- Microsoft ASP.NET 4 : The HttpApplication Class and HTTP Modules - Overriding HttpApplication
- Microsoft ASP.NET 4 : Diagnostics and Debugging - Error Pages
- Microsoft ASP.NET 4 : Diagnostics and Debugging - Debugging with Visual Studio
- Microsoft ASP.NET 4 : Diagnostics and Debugging - Application Tracing
- Microsoft ASP.NET 4 : Diagnostics and Debugging - Page Tracing
 
 
Most view of day
- Printing from a Program, Printing a Document - Print a Document Using the Default Printer, Print a Document Using a Specific Printer
- Microsoft Visio 2010 : Linking External Data to Shapes (part 5) - Using Link Data - Preparing a Master for Link Data , Importing Data for Link Data
- Communicating with Internet Email : Working with Identities
- Planning and Designing a Public Key Infrastructure : Identifying PKI Requirements
- Microsoft OneNote 2010 : Doing Research with Linked Notes (part 2) - Ending a Linked Notes Session, Viewing Linked Notes
- Windows Live Services That Make Windows 7 Better (part 5) - Windows Live Essentials
- Microsoft Exchange Server 2007 : Implementing Client Access and Hub Transport Servers - Understanding the Hub Transport Server
- Microsoft Exchange Server 2013 : Creating new mailboxes (part 3) - Default folders, Manipulating mailbox settings
- Extending Dynamics GP with Free Software : Preventing date errors with DocDateVerify, Executing SQL from the Support Administrator Console
- Managing Windows 7 : Helping Each Other - Start the Session, Solve The Problem
Top 10
- Windows Server 2012 : Configuring IPsec (part 7) - Configuring connection security rules - Monitoring IPsec
- Windows Server 2012 : Configuring IPsec (part 6) - Configuring connection security rules - Creating a custom rule, Configuring authenticated bypass
- Windows Server 2012 : Configuring IPsec (part 5) - Configuring connection security rules - Creating an authentication exemption rule, Creating a server-to-server rule, Creating a tunnel rule
- Windows Server 2012 : Configuring IPsec (part 4) - Configuring connection security rules - Types of connection security rules, Creating an isolation rule
- Windows Server 2012 : Configuring IPsec (part 3) - Configuring IPsec settings - Customizing IPsec tunnel authorizations, Configuring IPsec settings using Windows PowerShell
- Windows Server 2012 : Configuring IPsec (part 2) - Configuring IPsec settings - Customizing IPsec defaults
- Windows Server 2012 : Configuring IPsec (part 1) - Understanding connection security
- Microsoft Project 2010 : Linking Tasks (part 8) - Auditing Task Links,Using the Task Inspector
- Microsoft Project 2010 : Linking Tasks (part 7) - Creating Links by Using the Mouse,Working with Automatic Linking Options
- Microsoft Project 2010 : Linking Tasks (part 6) - Creating Links by Using the Entry Table
 
 
Windows XP
Windows Vista
Windows 7
Windows Azure
Windows Server
Windows Phone
2015 Camaro