Drawing with DPI Aware Thick Pens

4/8/2010

At higher DPIs, the thickness of lines has to be increased in order to maintain their visual size. To be DPI aware, your application should scale the width of any pens with which it draws.

The behavior of the Windows Embedded CE Graphics Device Interface (GDI) with respect to drawing thick (greater than 1 pixel) lines makes precise and correct positioning tricky. For calls to the Windows Embedded CE-based functions LineTo and Polyline, GDI takes the specified origin point as the center of the pen's width. For lines with odd-numbered pixel thickness, the width of the line is equally distributed to each side of the origin point; but for lines with even-numbered pixel thickness, GDI biases the top and left sides.

If your application has been positioning lines without making assumptions about the thickness of pens, it will probably handle thicker pens due to high-DPI without any changes. But if it has been assuming a constant pen width, such as one pixel, then you should be aware of the effect that GDI's behavior can have on layouts.

This illustration shows how GDI's behavior can cause unexpected shifts in your layout. The following code is executed on a 96-DPI and a 192-DPI device, with a scaled pen selected into hDC, and the results are shown side-by-side.

1-pixel thick pen at 96-DPIfrom (1,1) to (6,6) 2-pixel thick pen at 192-DPIfrom (2,2) to (12,12)
Bb431776.a29f2796-0962-4ca0-b06b-583e8f822ccd(en-us,MSDN.10).gif
Bb431776.b860dd2d-ba47-4fbb-9901-82ffe2bbba4b(en-us,MSDN.10).gif
rgptEndpoints[0].x = SCALEX(1);
rgptEndpoints[0].y = SCALEY(1);
rgptEndpoints[1].x = SCALEX(6);
rgptEndpoints[0].y = SCALEY(6);
Polyline(hDC, rgptEndpoints, 2);

Although the use of the SCALEX and SCALEY macros correctly placed the origin, and the scaled pen ensured a line of the right thickness, the line draws higher in 192-DPI than in 96-DPI. This is because GDI centers the ink around the origin and biases to the top.

Included in the code example are some helpers that let you precisely control how to draw thick lines relative to origin coordinates. The HIDPI_Rectangle and HIDPI_Polyline functions in the CrosswordSample code wrap GDI calls that are likely to be problematic. Returning to the previous example, here is how you can draw a DPI-aware horizontal line in which the 192-DPI layout will match the 96-DPI layout.

rgptEndpoints[0].x = SCALEX(1);
rgptEndpoints[0].y = SCALEY(1);
rgptEndpoints[1].x = SCALEX(6);
rgptEndpoints[0].y = SCALEY(6);
HIDPI_Polyline(hDC, rgptEndpoints, 2, PS_DOWNRIGHT);

See Also

Concepts

Developing DPI Aware Applications
High DPI Display