6 out of 8 rated this helpful - Rate this topic

Tutorial: Writing High-DPI Win32 Applications

Estimated time to complete this tutorial: 25 minutes.

Note  This tutorial is designed to run on Windows 7 with Microsoft Visual Studio 2008 installed; however, the project files work on Windows Vista as well.

It contains the following five steps:

After completing this tutorial, you will know the following:

  • Why it is increasingly important to make your application DPI-aware.
  • How to ensure that the computer is in high DPI mode.
  • How to compare UI elements at the 144 DPI setting and the 96 DPI setting.
  • How to mark the application as DPI-aware.
  • How to scale the button size and layout.
  • How to scale the window size and use the default theme text API for text.

Why High DPI Support Is Important

Our end user research produced some very surprising results -- only about 55% of users actually set their display to the maximum resolution. This means that almost half of all users are not taking advantage of their display at full fidelity. The research results are shown in the following table.

Monitor's maximum resolution % of users set to maximum
1280X102456%
1400X1050 79%
1600X1200 32%
1680X1050 66%
1920X1050 39%
1920X1200 78%
Average set to maximum 55%

 

Most users who use lower resolution do so because they find the text too small at the maximum resolution. However, simply reducing the resolution has some negative side effects, such as:

  • ClearType is not rendered correctly at non-native resolution.
  • Users cannot see high definition content at full fidelity.
  • High resolution photos cannot be rendered in maximum fidelity in these scenarios.

To increase the size of the text, users are encouraged to increase the DPI setting to take advantage of their display at high fidelity, rather than reduce the resolution and have to put up with the negative side effects. While this solves the problem with loss of fidelity, applications that are not DPI-aware often have some unpleasant visual artifacts, as you will experience later in this module.

In Windows 7 there will be a greater level of adoption of high DPI for the following reasons:

  • More OEMs are expected to start shipping laptops with high DPI settings preconfigured.
  • Clean installations of Windows 7 have capable devices preconfigured to high DPI.
  • The Control Panel UI for high DPI is easier to find.

Adding high DPI support to your application is more important than ever. The following steps take a basic Win32 application and show you how to make it DPI-aware.

Step 1: Ensure That the Computer Is in High DPI Mode

In this step, you will ensure that your computer running Windows 7 is in high DPI mode at the 144 DPI setting.

To check that your computer is set to the 144 DPI setting

  1. On the Start menu, click Control Panel.
  2. In the Search text box at the upper-right corner of Control Panel, type "display", and a list of results appears, as shown in the following screen shot.

    Screen shot showing a list of results for display in Control Panel.

  3. Click the Display heading, and you should see a dialog box that looks like the following screen shot, with the Larger - 150% radio button selected. This indicates that the computer is set to the 144 DPI setting, because 150% of the normal DPI (96 DPI) is equal to 144 DPI.

    Screen shot showing where to check custom text size.

Step 2: Run the Application at the 144 DPI Setting

In this step, first download the application project at the MSDN Code Gallery. Compile it and then run it at the 144 DPI setting to compare the UI elements to those at the 96 DPI setting.

To run the application at the 144 DPI setting

  1. In Visual Studio 2008, open the High DPI HOL.sln solution.
  2. On the Build menu, click Build Solution.
  3. On the Debug menu, click Start Debugging. The application appears, as shown in the following screen shot.

Screen shot showing the UI of the application running at the 144 DPI setting.

To compare the UI at the 144 DPI setting to the 96 DPI setting

The following screen shot shows how the UI of the application looks when running at the 96 DPI setting. Now compare this UI to the UI from the 144 DPI setting.

Screen shot showing the UI of the application running at the 96 DPI setting.

The following table summarizes the appearances of the application UI at the 144 DPI setting as compared to at the 96 DPI setting.

UI element Appearance at 144 DPI
Size of the window frame Larger
Size of the buttons Larger
Size of the text Larger
Clipped text on the buttons Yes
Clipped text in the window Yes
Blurry effect Yes

 

Notice that the application is blurry, the text is clipped, and the sizes of the buttons and window frame are increased. This is caused by the application’s incompatibility with the default scaling offered by DPI virtualization.

When the DPI is set to 144, the operating system automatically enables DPI virtualization. This concept of DPI virtualization was introduced in Windows Vista and is also known as DPI scaling, which means to scale the text and window size of the applications that are not DPI-aware.

When your application relies solely on DPI virtualization to scale its UI elements, it might produce visual artifacts due to potential incompatibility with the DPI scaling. The preceding sample demonstrated that. To fix the problem, you need to programmatically opt out of the DPI virtualization by declaring your application as DPI-aware.

In the cases where applications have already been deployed, you can manually opt them out of the automatic DPI virtualization. For more information, see the "DPI Virtualization" topic in Writing DPI-Aware Win32 Applications.

Step 3: Mark the Application As DPI-Aware

In this step, you mark the application as DPI-aware to opt out of the DPI virtualization. To do so, first add the DPI-aware manifest entry to the application. This manifest entry tells Windows that the application is DPI-aware, so Windows disables DPI virtualization. And then run the application, compare the UI at the 144 DPI setting to the UI at the 96 DPI setting; finally jot down any UI issues.

Note  This step continues from the previous steps.

To add the DPI-aware manifest entry to the application

  1. On the Visual Studio Project menu, click HandsOnLab Properties.

  2. In the HandsOnLab Property Pages dialog box, expand the Configuration Properties, expand the Manifest Tool, and then click Input and Output.

  3. In the right pane, in the Additional Manifest Files text box, type DeclareDPIAware.manifest, as shown in the following screen shot, and then click OK.

    Screen shot showing the Property Pages with the Additional Manifest Files text box.

    Note  The project that you just downloaded contains a file named DeclareDPIAware.manifest. The following is the file content.

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
      <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
          <dpiAware>true</dpiAware>
        </asmv3:windowsSettings>
      </asmv3:application>
    </assembly>
    
    
  4. Recompile the application and run it. The application appears as shown in the following screen shot:

    Screen shot showing the UI of the application with a manifest entry.

To compare the UI elements at the 144 DPI setting to those at the 96 DPI setting

The following table shows the UI elements of the application at the 144 DPI setting as compared to those at the 96 DPI setting. Notice that adding the manifest entry to the application disables the DPI virtualization, and thus fixes the blurry issue and keeps the size of the window and buttons the same as those at the 96 DPI setting.

UI element Appearance at the 144 DPI setting
Size of the window frame Same
Size of the buttons Same
Size of the text Larger
Clipped text on the buttons Yes
Clipped text in the window Yes
Blurry effect Fixed

 

Step 4: Fix the Button Size and Layout

In this step, you fix the button size and layout. To do so, scale the size of the buttons from raw pixels to relative pixels to appropriately display the text size, and then scale the layout of the buttons from raw pixels to relative pixels to fix the button layout.

Note   This step continues from the previous steps.

To scale the button size

  1. Open the HandsOnLab.cpp file. In the DemoApp::CreateChildWindows method, find the section where button initialization is specified.
  2. Add the following code to scale the size of all three buttons.
    
    // Now set up the size of the buttons that we will create.
       SIZE buttonSize = { 60, 26 };
       g_metrics.ScaleSize(&buttonSize);
    
    
    
    The g_metrics variable is an instance of the CDPI class, and the g_metrics.ScaleSize method scales from raw pixels to relative pixels.
  3. Save the file, recompile, and then run the application. The application appears as shown in the following screen shot, with the appropriately scaled button size.

    Screen shot showing the UI of the application with the appropriately scaled button size.

To scale the button layout

  1. In the DemoApp::CreateChildWindows method, add the following code.
    
     // Button 1 position.
        POINT ptButton1Pos = { 10, 55 };
        g_metrics.ScalePoint(&ptButton1Pos);
        
        // Button 2 position is 75 pixels to the right of Button 1. 
        POINT ptButton2Pos = { 85, 55 };
        g_metrics.ScalePoint(&ptButton2Pos);
        
        // Button 3 is 75 pixels to the right of button 2.
        POINT ptButton3Pos = { 160, 55 };
        g_metrics.ScalePoint(&ptButton3Pos);   
    
    
    

    The g_metrics.ScalePoint method scales points from raw pixels to relative pixels.

  2. Save the file, recompile, and then run the application. The application should look like the following screen shot, with the appropriately scaled button size and layout.

    Screen shot showing the UI of the application with the appropriately scaled button size and layout.

Step 5: Fix the Window Size and Clipped Text

In this step, you fix the window size and clipped text. To do so, scale the window size to the current DPI setting, and then use the default theme text to fix the clipped text. To scale the window properly, use the ScaleX and ScaleY functions of the CDPI class to convert raw pixels to relative pixels to scale the window size to the current DPI setting.

Note   This step continues from the previous steps.

To scale the window properly

  • In the DemoApp::Initialize method, find the call to the CreateWindow function, and then ensure that the nWidth and nHeight parameters that are passed in are scaled by using the respective g_metrics.ScaleY and g_metrics.ScaleY methods, as shown in the following code.

// Create window.
    m_hwnd = CreateWindow(
        TEXT("HighDPIDemoApp"),
        TEXT("High DPI Demo App"),
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        g_metrics.ScaleX(420),
        g_metrics.ScaleY(200),
        NULL,
        NULL,
        HINST_THISCOMPONENT,
        this
        );


To replace TextOut with the default theme text API

  1. In the DemoApp::OnRender method, comment out the TextOut function call.
  2. Uncomment the code for the theme text drawing. When you are done, the code should look like this.
    
    // TextOut(ps.hdc, rcText.left, rcText.top, szText, lstrlen(szText));
    // This is the recommended way of using the theme API to draw text.
    // You will un-comment this during the exercise to see how to properly draw
    // themed text.
    
    OffsetRect(&rcText, g_metrics.ScaleX(8), g_metrics.ScaleY(8));
    HTHEME hTheme = OpenThemeData(hWnd, VSCLASS_TEXTSTYLE);
    if (hTheme)
    {
          DrawThemeText(hTheme, ps.hdc, TEXT_BODYTEXT, 
                        0, szText, -1, DT_SINGLELINE, 0, &rcText);
          CloseThemeData(hTheme);
    }
    else
    {    
          // Visual styles are not enabled. 
          DrawText(ps.hdc, szText, -1, &rcText, DT_SINGLELINE);
    }
    
    
    
  3. Save the file, recompile, and then run the application. The application appears with all UI issues resolved, as shown in the following screen shot.

    Screen shot showing the UI of the application with all UI issues resolved.

Conclusion

In this tutorial, you learned why it is important to make your application DPI-aware and you performed the following exercises:

  • Marked your application as DPI-aware by using the manifest entry.
  • Tested your application at the 144 DPI setting.
  • Compared the UI elements at the 144 DPI setting to those at the 96 DPI setting.
  • Scaled the button size and layout, scaled the window size, and used the default theme text API for text.

To make your application truly high-fidelity DPI-aware, you should create multiple resolution versions of your images, bitmaps, icons, and toolbar buttons. Then you will have appropriately scaled images for different display resolutions without having the blurriness or pixelation associated with scaling small bitmaps. With those high-fidelity assets, you can select the appropriate bitmap based on the closest match to the current DPI setting and then scale to fit the precise setting.

 

 

Send comments about this topic to Microsoft

Build date: 10/27/2012

Did you find this helpful?
(1500 characters remaining)

Community Additions

ADD
© 2013 Microsoft. All rights reserved.