Programming .NET Framework 3.5 : An Introduction to .NET Compact Framework Graphics

6/5/2012 9:15:36 AM
In general, programs do not directly touch hardware to draw. Instead, programs use graphical libraries for drawing. Those libraries, in turn, rely on device drivers to touch the underlying hardware. And so, graphical output typically involves these software layers:
  • Drawing program

  • Graphics function library

  • Graphics device driver (display driver or printer driver)

The core graphics library on desktop Windows is the Graphics Device Interface (GDI, gdi32.dll). With .NET, Microsoft added a second library (GDI+, gdiplus.dll[1]) to add new drawing support. While GDI+ was intended to support managed-code drawing, the library is also accessible from native-mode application programmers: The library can be called from unmanaged (native-mode) C++ programs. On the desktop, these two graphics libraries—GDI and GDI+—provide the underpinnings for all of the .NET graphics classes. And so, with .NET Framework programs running on the Windows desktop, the architecture of graphical output involves the following elements:

[1] GDI+ is a native-mode, unmanaged-code library.

  • Managed-code program

  • Shared managed-code library (System.Drawing.dll)

  • GDI+ native-code library (gdiplus.dll)

  • GDI native-code library (gdi32.dll)

  • Graphics device driver (display driver or printer driver)

Windows CE supports a select set of GDI drawing functions. There is no library explicitly named “GDI” in Windows CE. Instead, the graphical output functions reside in the COREDLL.DLL library. These functions are exactly like their desktop counterparts, so even if there is no library named “GDI” in Windows CE, we refer to these functions as “GDI functions.”

Of the desktop’s 400 or so GDI functions, only 85 exist in Windows CE. Windows CE has no GDI+ drawing functions. This limits the extent to which Windows CE can support .NET drawing functions.

With these limits, you might wonder whether Windows CE can create interesting graphical output. The answer is a resounding “yes!” The functions that are present were hand-picked as the ones that programs tend to use most. It represents a good set of text, raster, and vector functions so that programs can draw rich text output, display bitmaps in a wide range of formats, and draw complex vector objects.

On both desktop and compact versions, the main .NET graphical library is System.Drawing.dll. At 59KB, the .NET Compact Framework library is significantly smaller than its 616KB desktop counterpart. While the desktop library supports five namespaces, the .NET Compact Framework version supports one: System.Drawing (plus tiny fragments of two other namespaces). The architecture for drawing from a .NET Compact Framework program is as follows:

  • Managed-code program

  • Managed-code library (System.Drawing.dll)

  • GDI functions in the native-code library (COREDLL.DLL)

  • Graphics device driver (display or printer)

From the arrangement of these software layers, a savvy .NET Compact Framework programmer can divine two interesting points: (1) The managed-code library depends on the built-in GDI drawing functions, and managed-code programs can do the same; and (2) as on the desktop, display screens and printers require a dedicated graphics driver to operate.

1. Drawing Surfaces

On the Windows desktop, there are four types of drawing surfaces:

  1. Display screens

  2. Printers

  3. Bitmaps

  4. Metafiles

When we use the term drawing surface, we mean either a physical drawing surface or a logical drawing surface. Two of the four drawing surfaces in the list are physical drawing surfaces, which require dedicated device drivers: display screens and printers. The other two drawing surfaces are logical drawing surfaces: bitmaps and metafiles. These latter two store pictures for eventual output to a device.

Bitmaps and metafiles are similar enough that they share a common base class in the desktop .NET Framework: the Image[2] class. Metafiles are not officially supported in Windows CE, however, and so their wrapper, the Metafile[3] class, does not exist in the current version of the .NET Compact Framework. Because metafiles might someday be supported in a future version of the .NET Compact Framework, they are worth a brief mention here.

[2] System.Drawing.Image.

[3] System.Drawing.Imaging.Metafile.

1.1. Display Screens

The display screen plays a central role in all GUI environments because it is on the display screen that a user interacts with the various GUI applications. The real stars of the display screen are the windows after which the operating system gets its name. A window acts as a virtual console[4] for interacting with a user. The physical console for a desktop PC consists of a display screen, a mouse, and a keyboard. On a Pocket PC, the physical console is made up of a display screen, a stylus and a touch-sensitive screen for pointing, and hardware buttons for input (supported, of course, by the on-screen keyboard).

[4] A term we first heard from Marlin Eller, a member of the GDI team for Windows 1.x.

All graphical output on the display screen is directed to one window or another. Enforcement of window boundaries relies on clipping. Clipping is the establishment and enforcement of drawing boundaries; a program can draw inside clipping boundaries but not outside them. The simplest clipping boundaries are a rectangle. The area inside a window where a program may draw is referred to as the window’s client area.

1.2. Printers

Printers are the best-established and most-connected peripherals in the world of computers. While some industry pundits still rant about the soon-to-arrive paperless office, just the opposite has occurred. Demand for printed output has continued to go up, not down. Perhaps the world of computers—with its flashing LCD displays, volatile RAM, and ever-shrinking silicon—makes a person want something that is more real.

Printing from Windows CE–powered devices is still in its infancy, which is a nice way to say that it is not well supported. The official story is that users have not asked for it—in other words, there is not a good enough business case for adding better printing support. Someday that may change, but until then you are on your own when it comes to creating hard-copy output from a Windows Mobile device.

1.3. Bitmaps

Bitmaps provide a way to store a picture. Like its desktop counterparts, Windows CE supports device-independent bitmaps (DIBs) as first-class citizens. In-memory bitmaps can be created of any size[5] and treated like any other drawing surface. After a program has drawn to a bitmap, that image can be put on the display screen.

[5] The amount of available system memory limits the bitmap size.

If you look closely, you can see that Windows CE and the .NET Compact Framework support other raster formats. Supported formats include GIF, PNG, and JPEG. When Visual Studio .NET reads files with these formats (which it uses for inclusion in image lists, for example), it converts the raster data to a bitmap. The same occurs when a PNG or JPEG file is read from the object store into a .NET Compact Framework program. Whatever external format is used for raster data, Windows CE prefers bitmaps.

1.4. Metafiles

A second picture-storing mechanism supported by desktop Windows consists of metafiles. A metafile is a record-and-playback mechanism that stores the details of GDI drawing calls. The 32-bit version of Windows metafiles are known as Enhanced Metafiles (EMFs). The following Win32 native metafile functions are exported from COREDLL.DLL but are not officially supported in Windows CE, although they might gain official support in some future version of Windows CE:

  • CreateEnhMetaFile

  • PlayEnhMetaFile

  • CloseEnhMetaFile

  • DeleteEnhMetaFile

1.5. Supported Drawing Surfaces

Of these four types of drawing surfaces, three have official support in Windows CE: display screens, printers, and bitmaps. Only two are supported by the .NET Compact Framework: display screens and bitmaps. Support for bitmaps centers on the Bitmap[6] class. We start this discussion of graphical output with the drawing surface that is the focus in all GUI systems: the display screen.

[6] System.Drawing.Bitmap.

2. Drawing Function Families

All of the graphical output functions can be organized into one of three drawing function families:

  • Text

  • Raster

  • Vector

Each family has its own set of drawing attributes and its own logic for how its drawing is done. The distinction between these three kinds of output extends from the drawing program into the graphics device drivers. Each family is complex enough for a programmer to spend many years mastering the details and intricacies of each type of drawing. The drawing support is rich enough, however, so that you do not have to be an expert to take advantage of what is offered.

2.1. Text Output

For drawing text, the most important issue involves selection of the font because all text drawing requires a font, and the font choice has the greatest impact on the visual display of text. The only other drawing attribute that affects text drawing is color—both the foreground text and the color of the background area. 

2.2. Raster Output

Raster data involves working with arrays of pixels, sometimes known as bitmaps or image data. Internally, raster data is stored as a DIB. Six basic DIB formats are supported in the various versions of Windows: 1, 4, 8, 16, 24, and 32 bits per pixel. Windows CE adds a seventh DIB format to this set: 2 bits per pixel.

Windows CE provides very good support for raster data. You can dynamically create bitmaps, draw on bitmaps, display them for the user to see, and store them on disk. A bitmap, in fact, has the same rights and privileges as the display screen. By this we mean you use the same set of drawing functions both for the screen and for bitmaps. This means you can use bitmaps to achieve interesting effects by first drawing to a bitmap and subsequently copying that image to the display screen. An important difference from desktop versions of Windows is that Windows CE does not support any type of coordinate transformations, and in particular there is no support for the rotation of bitmaps; the .NET Compact Framework inherits these limitations because it relies on native Win32 API functions for all of its graphics support.

2.3. Vector Output

Vector drawing involves drawing geometric figures such as ellipses, rectangles, and polygons. There are, in fact, two sets of drawing functions for each type of figure. One set draws the border of geometric figures with a pen. The other set of functions fills the interiors of geometric figures using a brush.

3. .NET Compact Framework Graphics

The .NET Framework has six namespaces that support the various graphical output classes. In the .NET Compact Framework, just one namespace has made the cut: System.Drawing. This namespace and its various classes are packaged in the System.Drawing.dll assembly. For a detailed comparison between the graphics support in the .NET Framework and in the .NET Compact Framework, see the sidebar Comparing Supported Desktop and Smart-Device Drawing.

Comparing Supported Desktop and Smart-Device Drawing

The System.Drawing namespace in the .NET Compact Framework holds the primary elements used to draw on a device screen from managed code. The desktop .NET Framework provides five namespaces for creating graphical output, but in the .NET Compact Framework this has been pared back to two: System.Drawing and System.Drawing.Design (plus some fragments from two other namespaces).

Table 1 summarizes the .NET namespaces supported in the desktop .NET Framework, along with details of how these features are supported in the .NET Compact Framework. The System.Drawing namespace supports drawing on a device screen. A second namespace, System.Drawing.Design, helps when building a custom control. In particular, this namespace contains elements used to support design-time drawing of controls (i.e., drawing controls while they are being laid out inside the Designer). The elements of this namespace reside in the System.CF.Design.dll assembly, a different name from the assembly name used for the desktop. The change in the filename makes it clear that this file supports .NET Compact Framework programming.

Table 1. Desktop .NET Framework Drawing Namespaces in the .NET Compact Framework
NamespaceDescriptionSupport in the .NET Compact Framework
System.DrawingCore drawing objects, data structures, and functionsA minimal set that allows for the drawing of text, raster, and vector objects with no built-in coordinate transformation
System.Drawing.DesignSupport for the Designer and the various graphics editors of Visual Studio .NETSupport provided by a .NET Compact Framework–specific alternative library named System.CF.Design.dll
System.Drawing.Drawing2DSupport for advanced graphics features, including blends, line caps, line joins, paths, coordinate transforms, and regionsNot supported in the .NET Compact Framework (except for the CombineMode enumeration)
System.Drawing.ImagingSupport for storage of pictures in metafiles and bitmaps; bitmap conversion; and management of metadata in image filesNot supported in the .NET Compact Framework (except for the ImageAttributes class)
System.Drawing.PrintingRich support for printing and the user interface for printingNot supported in the .NET Compact Framework
System.Drawing.TextFont managementNot supported in the .NET Compact Framework

On the surface, it would be easy to conclude that Microsoft gutted the desktop System.Drawing.dll library in creating the .NET Compact Framework edition. For one thing, the desktop version is a whopping 456KB, while the compact version is a scant 38KB. What’s more, the desktop version supports 159 classes, while the compact version has a mere 17 classes. A more specific example of the difference between the desktop .NET Framework and the .NET Compact Framework—from a drawing perspective—is best appreciated by examining the Graphics class (a member of the System.Drawing namespace). The desktop .NET Framework version of this class supports 244 methods and 18 properties; the .NET Compact Framework version supports only 26 methods and 2 properties. By this accounting, it appears that the prognosis of “gutted” is correct. Yet, as any thinking person knows, looks can be deceiving.

To better understand the differences between the desktop .NET Framework and the .NET Compact Framework, we have to dig deeper into the Graphics class. To really see the differences between the desktop and compact versions, we must study the overloaded methods. If we do, we see that the desktop .NET Framework provides many overloaded methods for each drawing call, while the .NET Compact Framework provides far fewer. For example, the desktop .NET Framework provides six different ways to call DrawString (the text drawing function), while there is only one in the .NET Compact Framework. And there are 30 versions of DrawImage (the function for drawing a bitmap) in the desktop .NET Framework but only 4 in the .NET Compact Framework.

We have, in short, fewer ways to draw objects—but in general we can draw most of the same things with the .NET Compact Framework that we can draw on the desktop. This supports a central design goal of Windows CE, which is to be a small, compact operating system. Win32 programmers who have worked in Windows CE will recognize that a similar trimming has been done to define the Windows CE support for the Win32 API. Instead of calling this a “subset,” we prefer to take a cue from the music recording industry and use the term greatest hits. The .NET Compact Framework implementation of the System.Drawing namespace is, we believe, the greatest hits of the desktop System.Drawing namespace.

In comparing the desktop .NET Framework to the .NET Compact Framework, an interesting pattern emerges that involves floating-point numbers. In the desktop .NET Framework, most of the overloaded methods take floating-point coordinates. For all of the overloaded versions of the DrawString methods, you can use only floating-point coordinates. In the .NET Compact Framework, few drawing functions have floating-point parameters—most take either int32 or a Rectangle to specify drawing coordinates. A notable exception is the DrawString function, which never takes integer coordinates in the desktop .NET Framework; in the .NET Compact Framework, it is the sole drawing method that accepts floating-point values.

It is worth noting that the underlying drawing functions (both in the operating system and at the device driver level) use exclusively integer coordinates. The reason is more an accident of history than anything else. The Win32 API and its supporting operating systems trace their origins back to the late 1980s, when the majority of systems did not have built-in floating-point hardware. Such support is taken for granted today, which is no doubt why the .NET Framework has such rich support for floating-point values.

A fundamental part of any graphics software is the coordinate system used to specify the location of objects drawn on a drawing surface. The desktop .NET Framework supports seven distinct drawing coordinate systems in the GraphicsUnit enumeration. Among the supported coordinate systems are Pixel, Inch, and Millimeter. While the .NET Compact Framework supports this same enumeration, it has only one member: Pixel. This means that when you draw on a device screen, you are limited to using pixel coordinates. One exception involves fonts, whose height is always specified in Point units.

This brings up another difference between the desktop .NET Framework and the .NET Compact Framework: available coordinate transformations. The desktop provides a rich set of coordinate transformations—scrolling, scaling, and rotating—through the Matrix class and the 3 × 3 geometric transform provided in the System.Drawing.Drawing2D namespace. The .NET Compact Framework, by contrast, supports no coordinate mapping. That means that, on handheld devices, application software that wants to scale, scroll, or rotate must handle the arithmetic itself because neither the .NET Compact Framework nor the underlying operating system provides any coordinate transformation helpers. What the .NET Compact Framework provides, as far as coordinates go, is actually the same thing that the underlying Windows CE system provides: pixels, more pixels, and only pixels.

While it might be lean, the set of drawing services provided in the .NET Compact Framework is surprisingly complete. That is, almost anything you can draw with the desktop .NET Framework can be drawn with the .NET Compact Framework. The key difference between the two implementations is that the desktop provides a far wider array of tools and helpers for drawing. Programmers of the desktop .NET Framework are likely to have little trouble getting comfortable in the .NET Compact Framework, once they get used to the fact that there are far fewer features. But those same programmers are likely to be a bit frustrated when porting desktop .NET Framework code to the .NET Compact Framework world and are likely to have to rewrite and retrofit quite a few of their applications’ drawing elements.

3.1. The Role of the Graphics Class

The most important class for creating graphical output is the Graphics[7] class. It is not the only class in the System.Drawing namespace, but only the Graphics class has drawing methods. This class holds methods such as DrawString for drawing a string of text, DrawImage for displaying a bitmap onto the display screen,[8] and DrawRectangle for drawing the outline of a rectangle. Here is a list of the other classes in the System.Drawing namespace for the .NET Compact Framework:

[7] System.Drawing.Graphics.

[8] DrawImage can also be used to draw bitmaps onto other bitmaps.

  • Bitmap

  • Brush

  • Color

  • Font

  • FontFamily

  • Icon

  • Image

  • Pen

  • Region

  • SolidBrush

  • SystemColors

These other classes support objects that aid in the creation of graphical output, but none have any methods that actually cause graphical output to appear anywhere. So, while you are going to need these other classes and will use these other classes, they play a secondary role to the primary graphical output class in the .NET Compact Framework: Graphics.

3.2. Drawing Support for Text Output

Table 2 summarizes the methods of the Graphics class that support text drawing. The DrawString method draws text, while the MeasureString method calculates the bounding box of a text string. This calculation is needed because graphical output involves putting different types of graphical objects on a sea of pixels. When dealing with a lot of text, it is important to measure the size of each text box to make sure the spacing matches the spacing as defined by the font designer. Failure to use proper spacing creates a poor result. In the worst cases, it makes the output of your program unattractive to users. Even if a user does not immediately notice minor spacing problems, the human eye is very finicky about what text it considers acceptable. Poor spacing makes text harder to read because readers must strain their eyes to read the text. Properly spaced text makes readers—and their eyes—happier than poorly spaced text does.

Table 2. System.Drawing.Graphics Methods for Text Drawing
DrawStringDraws a single line of text using a specified font and text color
MeasureStringCalculates the width and height of a specific character string using a specific font

3.3. Drawing Support for Raster Output

Table 3 summarizes the methods of the Graphics class that draw raster data. We define raster graphics as those functions that operate on an array of pixels. Two of the listed functions copy an icon (DrawIcon) or a bitmap (DrawImage) to a drawing surface. The other two methods fill a rectangular area with the color of an indicated brush.

Table 3. System.Drawing.Graphics Methods for Raster Drawing
ClearAccepts a color value and uses that value to fill the entire surface of a window or the entire surface of a bitmap
DrawIconDraws an icon at a specified location. An icon is a raster image created from two rectangular bitmap masks. The DrawIcon method draws an icon by applying one of the masks to the drawing surface, using a Boolean AND operator, followed by the use of the XOR operator to apply the second mask to the drawing surface. The benefit of icons is that they allow portions of an otherwise rectangular image to display the screen behind the icon. The disadvantage of icons is that they are larger than comparable bitmaps and also slower to draw
DrawImageDraws a bitmap onto the display screen or draws a bitmap onto the surface of another bitmap
FillRegionFills a region with the color specified in a brush. A region is defined as a set of one or more rectangles joined by Boolean operations

3.4. Drawing Support for Vector Output

Table 4 summarizes the seven methods in the Graphics class that draw vector Graphics objects in the .NET Compact Framework. There are substantially fewer supported vector methods than in the desktop .NET Framework. The vector methods whose names start with Draw draw lines. The vector methods whose names start with Fill fill areas.

Table 4. System.Drawing.Graphics Methods for Vector Drawing
DrawEllipseDraws the outline of an ellipse using a pen
DrawLineDraws a straight line using a pen
DrawPolygonDraws the outline of a polygon using a pen
DrawRectangleDraws the outline of a rectangle using a pen
FillEllipseFills the interior of an ellipse using a brush
FillPolygonFills the interior of a polygon using a brush
FillRectangleFills the interior of a rectangle using a brush
  •  Programming .NET Framework 3.5 : Placing Text
  •  Macro Marvel by Peiling Lee
  •  Flora - Nature - Photo Expert (Part 6) - Fungi
  •  Flora - Nature - Photo Expert (Part 5) - Creative blur
  •  Flora - Nature - Photo Expert (Part 4) - Viewpoint
  •  Flora - Nature - Photo Expert (Part 3) - Flowers, Depth-of-field & Lighting
  •  Flora - Nature - Photo Expert (Part 2) - Len accessories, Lighting aids, Tripods and alternative camera supports
  •  Flora - Nature - Photo Expert (Part 1)
  •  Epic Moments in Sports (Part 2)
  •  Epic Moments in Sports (Part 1)
  •  Hanns.G HL272 27” LED display
  •  PhotoDirector 3 - Gets snap happy
  •  Microsoft Sued Comet For Making 94,000 Copies Of Counterfeit Windows
  •  TV Became Smarter & Friendlier : Ubuntu TV, MySpace TV released
  •  Provide Resources For The Olympics (Part 2)
  •  Provide Resources For The Olympics (Part 1)
  •  Fujifilm Released The First Version Of CSC
  •  OLED Technology Casts A Spell On Big Screen TV
  •  Netflix Introduces Streaming Services In England
  •  Intel Introduced The Future Of Ultrabook
    Top 10
    Primer – Choosing And Using Peripheral Buses (Part 2)
    Primer – Choosing And Using Peripheral Buses (Part 1)
    SanDisk ReadyCache 32GB - Caching Solution SSD
    Windows 8 Tips And Tricks – Jan 2013
    Lenovo IdeaPad S400 - Stylish And Affordable Laptop
    Nokia Lumia 920 - Super Smart, Super-Size Handset
    Optimus L9 - The Nicest Phone In LG's 'L' Line
    Bits Of Bytes
    Happy iMas (Part 2)
    Happy iMas (Part 1)
    Most View
    Windows 7 : Maintaining Your Hard Drive
    Implementing and Validating SharePoint 2010 Security : Using IPsec for Internal SharePoint Encryption
    New or Updated Group Policy Settings in Windows Vista
    Exchange Server 2010 : Monitoring and Troubleshooting Unified Messaging
    AMD Radeon HD 7950 3GB vs. Nvidia GeForce GTX 660 Ti 2GB vs. Nvidia GeForce GTX 670 2GB (Part 2)
    Rise Of The Mobile Processors (Part 1)
    The Linux Build: Part For Penguins (Part 5)
    Advanced ASP.NET : Output Caching
    Iwork Pro : Export Strength
    Choose The Right Business Broadband (Part 2)
    Editions of SQL Server 2008
    Deploying the Client for Microsoft Exchange Server 2010 : Planning Considerations and Best Practices
    Kingston SSDNow mS100 64GB - One Of The Cheapest SSDs Around
    Linking PCs with a Network : Connecting to and Sharing Files with Other PCs on Your Network, Sharing a Printer on the Network
    Most Favorite Education Apps For Your Smartphone – November 2012
    Nikon Launched The D800 And D800E
    Troubleshooting Reference: Projectors
    MySQL for Python : Passing a query to MySQL
    Sony RX100 - Music To Your Ears!
    ASUS RT-N56U