Develop applications that can identify DPI
Release Date: 8/30/2004
| Update Date: 8/30/2004
Microsoft
Applicable to:
Pocket PC Based on Windows MobileTM 2003 Second Edition
Smartphone Based on Windows MobileTM 2003 Second Edition
Microsoft Embedded Visual C 4.0
Summary: Pocket PC and SmartPhone Based on Windows Mobile 2003 Second Edition can be run with higher resolution than early devices. Understand the application to determine the DPI of the device and the changes you need to use using a high DPI display.
Download Crossword.msi from the Microsoft Download Center.
This page
Introduction Key problem old-style support GAPI old-style support summary
Introduction
With the improvement of displays technology, more pixels are placed in the same area is become possible. You can use this increased resolution to place more items on the screen, or use it to more clearly draw the same item. In the latter case, it is called a display that has increased the number of points (DPIs) per inch; the DPI is a logic value indicating the pixel density of the display area.
The print media has taken high DPI technology for a long time. The document printed on the 1200 DPI printer is the same as the number of texts printed by the 300 DPI printer, but the text is clearer.
Based on Windows Mobile PCKET PC and Smartphone traditionally uses 96 DPI monitors, but Windows Mobile 2003 SECOND Edition can run with higher resolution. Upgrade your application to support DPI identification, not only make sure that you can display properly on high DPI devices, you can also make your app offer the following high DPI advantages:
• Clear text: Almost no price will be the most significant improvement. Each application that recognizes DPI and using a TrueType font can inherit this improvement. • More detailed graphics: If some steps are taken to provide high resolution bitmap, the application can display more detailed icons and graphics using improved resolution.
This article describes what changes you need to make to make it capable of determining the DPI of the device and a display with a higher DPI.
Back to top
The key issue
In applications that identify DPIs for Pocket PC and Smartphone, you need to focus on the following three common fields:
• Layout • Text and font • Image
layout
If you assume that 96 DPI pixel coordinates to specify the location and size of the UI element, these elements will be incorrect in high DPI devices. Typically, all UI elements should be arranged using scalable positions and size or with respect to controls, fonts, or system metrics.
You can use the Windows Mobile function getDeviceCaps and get the DPI of the display by incorporation of Logpixelsx or LogPixelsy as the second parameter. The CrosswordSample example demonstrates how to define scalex and scaley macros to apply proportional factors based on information in getDeviceCaps.
You can continue to use pixels as units, but you need to use the following techniques to eliminate assumptions about DPI:
• Use Scalex and Scaley Macro to zoom 96 DPI coordinates, or use GetSystemMetrics returned using GetSystemMetrics when appropriate. • Represents size or position relative to other controls. • Represents size or position relative to fonts.
The dialog has used the name to determine their layout, so they usually do not need to make special modifications, you can work on high DPI devices. Below is an example of a location window through the DPI identification function, where x, y, dx and dy are pixel coordinates with 96 DPI:
SetwindowPos (HWND, NULL, Scalex (x), Scaley (Y), Scalex (DX), Scaley (DY), SWP_NOZORDER);
If you choose to zoom 96 DPI pixel metrics, pay attention to the problem when using an integer. For example, because of rounding problems, Scalex (A B) may not be equal to (scalex (a) scalex (b)).
System metrics
To identify DPIs, the application cannot perform any assumptions for various screen elements pixels (such as icons size or border width). Based on Windows Mobile's Smartphone and Pocket PCs provide many system metrics to provide information about user systems. For example, the following information can be queried by the GetSystemMetrics Windows CE function.
• You should use getSystemMetrics or getSystemMetrics (SM_CXSCREEN) to get the screen size size. • GetsystemMetrics or getSystemMetrics (SM_CYBORDER) should be used to get the border size. • GetsystemMetrics or getSystemMetrics should be used to get large icons and small icon sizes using GetSystemMetrics or GetSystemMetrics.
Use rough drawing that can identify DPI
When using a higher DPI value, we must increase the thickness of the line to maintain a proportional visual size. To identify DPI, your application should scale the width of any brush for drawing.
The behavior of Windows Mobile Graphics Equipment Interface (GDI) related to drawing crude (greater than 1 pixel) is difficult to make accurate and correct positioning. For the call to the Windows Mobile function LINETO and POLYLINE, GDI uses the designated origin as the center of the brush width. For the width of the odd width, the width of the line is evenly distributed to both sides of the origin; however, for the lines of the even width, the GDI will be biased on the top and the left side.
If your application does not perform any assumptions about the brush width when the line is positioned, it may not change the brush that is widened due to high DPI. However, if it assumes a constant brush width (such as 1 pixel), you should pay attention to the impact of GDI behavior to the layout.
Figure 1 shows how GDI behavior results in an unexpected offset in your layout. The following code is performed on the 96 DPI device and the 192 DPI device, and the zoom brush is selected in the HDC, then display the following results in parallel:
Rgptendpoints [0] .x = scalex (1);
Rgptendpoints [0] .y = scaley (1);
Rgptendpoints [1] .x = scalex (6);
Rgptendpoints [1] .y = scaley (1);
POLYLINE (HDC, RGPtendPoints, 2);
Figure 1. Accidental offset caused in the layout due to GDI behavior
Although using Scalex and Scaley macros: The zoom brush ensures that the correct width line is drawn, but the line drawn on the 192 DPI device is higher than the line drawn on the 96 DPI device. This is because GDI distributes ink around the origin, and the lines of even width are biased on top.
A number of Helper functions are included in the CrosswordSample code that allows you to accurately control how to draw coarse lines relative to the origin coordinate. The HIDPI_Rectangle and HIDPI_POLYLINE functions in the code are packaged in GDI calls that may have problems. Returns to the previous example, the following code demonstrates how to draw horizontal lines that can identify DPI, and make 192 DPI layouts with 96 DPI layout: RGPTENDPOINTS [0] .x = scalex (1);
Rgptendpoints [0] .y = scaley (1);
Rgptendpoints [1] .x = scalex (6);
Rgptendpoints [1] .y = scaley (1);
HIDPI_POLYLINE (HDC, RGPTENDPOINTS, 2, PS_DOWNRIGHT);
Internet Explorer and HTML controls
The HTML layout is an exception to the rule of all pixel coordinates should be scaled. On Windows Mobile-based Pocket PC, Internet Explorer dedicates with 96 DPI pixels to explain the pixel coordinates in HTML. Although the relative coordinates are used in HTML (for example, 50% of the table is defined as a surface width) is always the best choice, if you are currently using the pixel metric, they will continue to produce the same layout under higher DPI. .
However, for Windows Mobile's SmartPhone, it is not the case. Pixel coordinates will continue to reference the actual pixels. Therefore, high resolution Smartphone will display more web page compared to low resolution Smartphone, and may render web pages in different ways.
At the device side, you can determine the screen size via Window.Screen.Width and Window.Screen.Height Microsoft Jscript variables. If you wish to understand the screen size of the device on the web server, you can implement it by querying the http_ua_pixels header.
Text and font
Although the TrueType font can scale well, they cannot be linearly scaled: adding DPI 10% to usually increase the length of the string to 10%. Cumulative effects (especially in a longer string) may result in relatively short text using different resolutions, or cut short, or accidental. Therefore, you need to use the Windows Mobile's getTextExtent function, instead of how much space will occupy the string. For static layouts such as dialogs, you should assign some extra width for text elements to accommodate any DPI.
In addition, different fonts show different nonlinear scaling effects, which means that use a variety of fonts on the screen, which may cause certain fonts that can cause certain fonts in proportion to other fonts when using different resolutions.
Create fonts that identify DPI
When you create a font for SmartPhone and Pocket PC, you should use pounds to specify the font size. Pounds refers to the logical size (1/72 of logical inch) instead of pixel height, so if it is used correctly, it itself can identify DPI. Below is an example of a code that creates a font that recognizes DPI using the pound size:
Logfont LF;
MEMSET (& lf, 0, sizeof (lf));
// set Other logfont values as appropriate.
Lf.lfheight = - (iPointSize * getDeviceCaps (HDC, Logpixelsy) / 72;
HFONT FONT = CREATEFONTINDIRECT (& LF); because lf.lfheight is an integer pixel height, it may be affected by the difference in rounding through the MULDIV call. The resulting font size may not be linearly zoomed from 96 DPI, but it will be a strict approximate value of the required pound size. This is a recommended font creation method.
If you need to make a more accurate linear scaling of the font pixel size, you can create a temporary font for 96 DPI, scaled its TemHeight text metrics, and create a new font based on the resulting value, as shown below. The font will be accurately linearly zoom height according to CDC :: GettextExtent, but its width may not be linearly zoomed, and it may also appear higher or short.
Note Even if you use this method to more accurately zoom in the font, you should not make a hypothesis on how much space will occupy on the string.
// CREATE FONT for 96 DPI.
Logfont LF;
MEMSET (& lf, 0, sizeof (lf));
// set Other logfont values as appropriate.
Lf.lfheight = -muldiv (iPointSize, 96, 72);
HFONT HFONT = CREATEFONTINDIRECT (& LF);
// scale the Temheight; Create Target Font.
TextMetric TM;
HDC HDC = GETDC (TARGET);
HFONT HFONTOLD = (HFONT) SelectObject (HDC, HFONT);
GetTextMetrics (HDC, & TM);
SELECTOBJECT (HDC, HFontold);
DeleteObject (HFONT);
ReleaseDC (Target, HDC);
Lf.lfheight = scaley (tm.tmheight);
HFont = CREATEFONTINDIRECT (& LF);
Get the user's font size
WINDOWS Mobile-based Pocket PC has a new control panel item (setting / screen / text size), which enables the user to choose a font size with the best display effect on the device screen. New applications written for Pocket PC should know this and should display their main UI text whenever possible use of the user-selected font size. To retrieve this value, use the SHGetuimetric function that is provided with the CrosswordSample code.
Long dwfontsize = 12;
SHGETUIMETRICS (Shuim_FontSize_pixel, & dwfontsize, sizeof (dwfontsize), null;
Lf.lfheight = -dwfontsize;
Your application should also know when the user font size is changed. To receive the notification, your application should call RegisterWindowMessage for the SH_UIMETRIC_CHANGE message. When your application receives the message, you should query SHGETUIMETRIC to find the new font size and then resemble itself.
image
In this article, the image refers to all raster-based image files (BMP / JPEG / GIF), icons, and cursors. Because they are fixed by the size indicated by pixel unit, it can be displayed uniquely issues that can identify applications for DPIs. Although image scaling can stretch the image to the correct logic size, it is necessary to truly use high DPI screens and provide a positive customer experience, you should manually recreate high visibility graphics.
Stretch image
If the display DPI is different from DPI for its design image, a stretch image is required to make it displayed in the correct physical size. However, you need to determine if you should stretch it while drawing an image, or whether you should create a new bitmap that only stretches once. If you can access the bitmap drawing code, change these code to stretch the memory than the mounting of the pull chart when loading. However, if you want to use a function or object that is not allowed to zoom a bitmap (for example, an image list function), you may need to stretch at the time of loading.
To stretch while drawing, you can zoom bitmap by calling the Windows Mobile function StretchBLT (instead of the Bitblt function). The following example assumes that the bitmap is created at 96 DPI (therefore should be stretched from its native width and height to scalex (width) and scaley):
Bitmap info;
GetObject (Bitmap, SizeOf (Info), (PTSTR) & info);
HDC HDCBitmap = CreateCompatibleDC (Target);
SelectObject (HDCBITMAP, BITMAP);
Stretchblt (Target, X, Y, Scalex (Info.BmWidth), Scaley (Info.Bmheight),
HDCBITMAP, 0, 0, INFO.BMWIDTH, INFo.Bmheight, Srccopy;
Deletedc (HDCBitmap);
To stretch while loading, you can use the hidpi_stretchbitmap or hidpi_imagelist_loadimage function supplied with the CrosswordSample code.
Use an image list to load a function to zoom bitmap
The imagelist_loadimage function assumes that it is not scaled, so it has only one parameter CX that represents the width of each image in the disk and the on-screen image. HIDPI_IMAGELIST_LOADIMAGE also has only one CX parameter indicating the width of each image on the disk. So, how does hidpi_imagelist_loadImage determine the width of each image should display on the screen? The answer is that the bitmap has a special field, which can identify the DPI resolution used when you create them: BiXPELSPERGETER and BIYPELSPERMETER fields in the BitmapInfo header. HIDPI_IMAGELIST_LOADIMAGE will check these fields and only scalable between the DPI resolution of this information and the screen.
By default, most graphic editing tools set these fields to 96 DPI. Very important point is whether your high resolution image list can set these fields correctly; otherwise, your bitmap will be incorrectly scaled correctly on a high DPI display.
Multiple images
An alternative method of scaling is to use multiple images, each image is created for different DPIs. This technology will produce the best results.
The .ICO format has been able to store multiple image sizes in a single file. When you load the icon or cursor, the application will look for the size of the getSystemMetrics function; then the system will select the closest image.
The following sample code shows how to choose from multiple non-.ico format images. To fully identify DPIs, the application should also scale the loaded bitmap based on the actual DPI of the device, as it should not make any assumptions on the available DPI resolution.
IF (GetDeviceCaps (HDC, Logpixelsx <130)
Bitmap = loadingbitmap (Hinstance, (char *) IDB_bitmap1);
Else
Bitmap = loadingBitmap (Hinstance, (char *) IDB_bitmap2); if the loaded bitmap has been created for the correct DPI, zoom it will not have any negative impact on performance or image quality.
Image in a static control
Windows Mobile automatically zooms in bitmaps in the static control of the High DPI display unless the size of the bitmap is equal to or greater than that contains its control (in this case, Windows CE will assume that the bitmap is created for high DPI) . This means that you may do any special changes correctly if you work properly.
To override this automatic zoom behavior, use the SS_REALSIMAGE style in the static control. This will prevent your image from being scaled. Conversely, if you want to zoom the image, but Windows CE does not perform this action, you can still use STM_SetImage to manually scales it before placing it in a static control.
Back to top
Old support
The high resolution Pocket PC based on Windows Mobile also provides an analog layer to implement backward compatibility with the old application. With this simulation layer, the display seems to be a traditional 240 x 320 display in the old application; however, the operating system scales all graphics to accommodate the actual display size. The height of the font will be linearly scaled, and the method used in the previous article is "creating a font" font "that can identify DPI.
The following factors will control whether the device should use analog layers on the application:
• Subsystem version information in the header. • Hi_RES_AWARE custom data in the resource of the executable file.
Subsystem version information is set in the compiled link phase. By default, applications compiled with Windows Mobile 2003 and 2002 SDK set this value to 4.20 or less; in the future version of the Pocket PC SDK, this value will be set to 4.21 and higher. Typically, applications with a subsystem version of 4.20 or lower are considered an old application and will pass through an analog layer.
You can use the hi_res_aware resources to rewrite this line of old applications. When the old application is loaded, the operating system will find this special resource item. The following procedure uses Microsoft Embedded Visual C to add it to the program.
Note In addition, you can also add down to your resource file directly:
Hi_res_aware ceux {1} // to Turn Off the emulation layer
Add Hi_RES_AWARE resources items to the program
1. From the INSERT menu, select Resource. 2. Click the CUSTOM button. 3. Enter CEUX as a resource type. 4. Set the resource data to 01 00. 5. Click the Properties tab. 6. Rename this item "Hi_RES_AWARE" (including quotation marks). (If the quotation is omitted, hi_res_aware will be incorrectly defined as a value in resource.h, and you will need to go back and remove the row from resource.h.) 7. Deactivate the External File check box.
Back to top
GAPI old support
Frequently using GAPI applications based on earlier versions of Pocket PC and Smartphone hardware for assumptions about screen size. In order to maintain backward compatibility with the old application, an analog layer has been added to GAPI. By default, the layer will scale the GAPI graph to accommodate the screen; however, it is possible to identify high-resolution applications to select bypass the analog layer to completely access the display hardware. To bypass the analog layer, the application should not call GXBEGINDRAW or GXENDDRAW. Instead, it should use the NESCAPE parameters equivalent to getRawframeBuffer to call EXTESCAPE and draw them with the returned frame pointer.
#define getrawframebuffer 0x00020001
#define Format_565 1
#define Format_555 2
#define Format_other 3
Typedef struct _rawframebufferinfo
{
Word wformat;
Word WBPP;
Void * pframepointer;
Int cxstride;
Int cystride;
Int cxpixels;
Int Cypixels;
RawframeBufferinfo;
// ...
Rawframebufferinfo RFBI;
HDC HDC = Getdc (NULL);
Extescape (HDC, GetrawFrameBuffer, 0, NULL,
SizeOf (RawframeBufferInfo), (char *) & rfbi;
ReleaseDC (NULL, HDC);
Old-style applications using GAPI can also get the same backward compatibility as non-GAPI applications. This means that the pen coordinates are scaled based on the subsystem version of the application executable - Even use GetRawFrameBuffer ExteScape.
Back to top
summary
If you don't want to worry about making existing applications to identify high-resolution issues, you should keep your code as the same, old-style support will properly zoom your fonts and graphics. However, if you want to use a high DPI screen by a method (eg, using a high resolution graphic), some simple steps can be taken to eliminate DPI dependence in the application.
Go to the original English page