Installation with DPI-Specific Resources

 

Microsoft Corporation

March 2004

Applies to:
   Windows Mobile™ 2003 Second Edition software for Pocket PCs
   Microsoft® eMbedded Visual C++® version 4.0

Summary: Learn how to separate a device's application resources into resolution-specific DLLs. (4 printed pages)

Download ResDLL Extension.msi from the Microsoft Download Center.

Contents

Introduction
Overview
Adding SetupDPI.DLL to the Project
Separating Resources into Subprojects
Modifying Application Source Code
Adding Registry Keys to Setup.INF
Getting the Device Resolution via RAPI
Conclusion

Introduction

As you are developing applications for new high-resolution Pocket PCs or Smartphones with 192 DPI resolution displays, you may wonder where the new high-resolution bitmaps and resources should go. The simplest solution is to include them in the same EXE alongside the old, low-resolution resources. However, this approach wastes storage space. Device screens only have one resolution, which never changes for that device. Therefore, if the application is deployed to a 96 DPI device, it doesn't need 192 DPI resources — and vice versa.

A better solution is to separate your application's resources into separate, resolution-specific DLLs. With this approach, the device can choose the appropriate resources to use during installation, and discard the resources it doesn't need. The ResDLL sample demonstrates how to do this.

Overview

It's a simple four-step process to create a single installation package that deploys different resources for high-resolution and low-resolution devices.

  1. Add SetupDPI.DLL to your project.
  2. Separate resources into two subprojects: Res_096 and Res_192.
  3. Modify your application's code to use the resource DLLs.
  4. Add registry keys to SETUP.INF file, and run CABWIZ to create the CAB file.

Adding SetupDPI.DLL to the Project

SetupDPI.DLL is a CE setup DLL that you can add to your installation CAB file. It is run after your applications install process has completed. The source code is provided as part of the ResDLL sample. You may use the pre-compiled version of SetupDPI.DLL, or you can incorporate the source code into your own CE setup DLL if you've already written one.

SetupDPI.DLL takes a list of files as input. It finds this list in the registry. For each file, if the filename ends in a number, and that number is the same as the display resolution, then SetupDPI.DLL renames the file, removing the number. Otherwise, it deletes the file. For example, if the display resolution is 192DPI, SetupDPI.DLL will delete RES_096.DLL and rename RES_192.DLL to RES.DLL.

The list of files is found under [HKLM\Software\Microsoft\SetupDPI]. Each key name is a path to a file; the value and type of the key is ignored. These registry keys will be populated by the CAB file as directed in your Setup.INF file (see step 4), and will be deleted by SetupDPI.DLL after setup is complete.

Separating Resources into Subprojects

You will need to create two DLL subprojects for your application using Microsoft® eMbedded Visual C++®. In the ResDLL sample, these are named Res_096 (which contains low-DPI resources) and Res_192 (which contains high-DPI resources).

When you create the resource DLL subprojects, make certain that every resource in Res_096 has the same resource ID as its counterpart in Res_192. The values for the resource IDs are defined in resource.h, but eMbedded Visual C++ does not support multiple RC files using a common resource.h. Therefore, you will need keep separate but identical copies of resource.h under the Res_096 and Res_192 directories.

By default, eMbedded Visual C++ assumes that new DLL project files will be executable and requires that they export DllMain. If you get a link error message for DllMain, the easiest way to fix it is to provide a stubbed-out implementation of DllMain.

Modifying Application Source Code

Your application should load the resource DLL during its initialization. Whenever your application uses a resolution-specific resource, it should use the module handle of the resource DLL.

#include "res_096\resource.h"
// ...
g_hInstRes = LoadLibrary(_T("RES.DLL"));
// ...
hBMP = LoadBitmap(g_hInstRes, MAKEINTRESOURCE(IDB_MYBITMAP)); 
CreateDialog(g_hInstRes, MAKEINTRESOURCE(IDB_MYDLG), hWnd, pDlgProc);

Adding Registry Keys to Setup.INF

To create your installation CAB files, use the CABWIZ tool provided with Embedded Visual C++. CABWIZ takes an INF file as input; the format of the INF file is documented on MSDN. You may want to use the Setup.INF file provided with the ResDLL sample as a template for your own application.

In the INF file, you will want to populate the registry with the list of files that SetupDPI.DLL should process. To do that, add the following to your AddReg section:

[AddRegSection]
   HKLM,Software\Microsoft\SetupDPI,%InstallDir%\Res_096.DLL,65537,0
   HKLM,Software\Microsoft\SetupDPI,%InstallDir%\Res_192.DLL,65537,0

When done, run the following from the command line:

cabwiz Setup.INF /CPU x86 ARM

Getting the Device Resolution via RAPI

If your installation package is too large to download to the device, it is possible to query the display resolution of the screen at installation time using the RAPI function call CeGetDesktopDeviceCaps and download only the appropriate resources to the device. This option is available to you only if your installer allows you to call custom executable code during installation. This approach will also require the user to connect their device to the desktop via Microsoft ActiveSync® at the time of installation. Where possible we recommend using the device side method for simplicity.

Conclusion

In order to save space on a high resolution Windows Mobile™-based device it is possible to split your resources and graphics into separate resource DLLs and then delete all but the DLL you need when the application is installed.