We can start by taking a look at the Bitmap class. This provides support for drawing graphical primitives such as lines and boxes. We can also use it to display text in a font of our choice. We can start by drawing a few simple lines on a bitmap and then displaying the bitmap.
To use the Bitmap class, you must have an LCD panel connected to your device, in either physical form or as an appropriately configured emulation. If you create a new .NET Micro Framework Window Application within Microsoft Visual Studio, Visual Studio will use the default Microsoft Emulator, allowing you to create and use Bitmap instances.
A Bitmap instance is created in the same way as an instance of any other class, by use of the new keyword and a call to a constructor of the class. In the case of the Bitmap class, there are two constructors. One accepts image data; the other creates an empty bitmap of a particular size. To start with, we will create an empty bitmap and then draw on it.
Bitmap myBitmap; myBitmap = new Bitmap( SystemMetrics.ScreenWidth, SystemMetrics.ScreenHeight);
This code creates a new bitmap instance that is the same size as the display. We obtain the display size from the SystemMetrics class, which is in the Microsoft.Spot.Presentation namespace.
The color of a new bitmap is black. It is not displayed at this point; you can think of it as a buffer into which you can place items ready for display. Positions within the bitmap are given in units of pixels, with the origin (0,0) being the top left corner of the display.
Once we have our bitmap, we can call methods to perform graphics operations on it.
myBitmap.DrawLine( Microsoft.SPOT.Presentation.Media.Color.White, // color 1, // line thickness 0, 0, // start myBitmap.Width, myBitmap.Height); // end
The DrawLine method accepts a set of parameters that define the color of the line, its thickness, and the start and end coordinates of the line. The preceding code would draw a white diagonal line from the top left corner of the display to the bottom right corner.
Drawing on a bitmap will not actually cause anything to appear on the display, because you need to make a call of the Flush method on the bitmap to tell it to display itself on the hardware.
At this point, the entire bitmap is copied onto the display and will become visible.
Figure 7-1 shows the line drawn by the program on a display that is 320 pixels wide and 240 pixels high. The line is drawn in white against the black background. It is possible use multiple bitmaps so that you can switch between different displays by calling the Flush method on the bitmap instance that you want to display. You could use this technique to perform simple double-buffered animation.
Figure 7-1: Drawing a single line on a display.
If you want to put only part of a bitmap onto the display, you can use a version of the Flush method that allows you to define a rectangular area of the source bitmap that is to be copied.
myBitmap.Flush( 60, 50, // source location 100, 150); // width and height of source
The first two parameters give the location in the source bitmap of the top left corner of the rectangle to be displayed. The second two parameters give the width and height of the rectangle.
The following code creates two bitmaps the size of the display. On bitmap b1, a line is drawn from the top left corner to the bottom right. On bitmap b2, a line is drawn from bottom left to top right. Then all of b1 is flushed to the display, followed by part of b2.
Bitmap b1 = new Bitmap(SystemMetrics.ScreenWidth, SystemMetrics.ScreenHeight); Bitmap b2 = new Bitmap(SystemMetrics.ScreenWidth, SystemMetrics.ScreenHeight); b1.DrawLine(Microsoft.SPOT.Presentation.Media.Color.White, 1, 0, 0, SystemMetrics.ScreenWidth, SystemMetrics.ScreenHeight); b2.DrawLine(Microsoft.SPOT.Presentation.Media.Color.White, 1, 0, SystemMetrics.ScreenHeight, SystemMetrics.ScreenWidth, 0); b1.Flush(); b2.Flush(120, 80, 80, 80);
Figure 7-2 shows how this appears on a display that is 320 pixels wide and 240 pixels high. The middle portion of the display has been overwritten with part of b1.
Figure 7-2: Display of a partial bitmap.
Note that this technique does not allow you to move graphical elements around the display because they must always be drawn in the same position on the display as they are in the bitmap. However, this technique does provide a means of reducing the amount of work required to update the display. If you have changed only part of a bitmap, you can just flush that part. You can use the DrawImage method, described later, to draw part of one bitmap on another.
Even though we are drawing only part of the bitmaps, it is important that we create the two bitmaps themselves with a size that exactly matches the display resolution; otherwise, the draw operation will not take place.
Our first code examples drew white lines. The color was selected using the White value of the Microsoft.SPOT.Presentation.Media.Color enumerated type. This particular type has only the values Black and White preset, but it is possible to select other colors, or even create your own color from red, green, and blue intensity values. To select from a range of preset colors, you can use the Microsoft.SPOT.Presentation.Media.Colors class, which contains the colors Black, Blue, Gray, Green, Red, and White. As an example, to draw a red line, you would use the following:
myBitmap.DrawLine( Microsoft.SPOT.Presentation.Media.Colors.Red, // color 1, // line thickness 0, 0, // start myBitmap.Width, myBitmap.Height); // end
The Color type provided in the .NET Micro Framework is not the same as that used in Windows Forms. Although the Color type in both cases is used to represent the color of an element in the display, the way that it is used and the means by which color is represented internally are different.
To select a particular color, a utility class is provided with a method that will create a custom color value from values for red, green, and blue.
c = ColorUtility.ColorFromRGB(255, 128, 0);
This would set the Color variable c to orange (that is, a mix of red and green). The values passed to the methods are byte type in the range 0 to 255. An actual color value can be represented as a single 24-bit value made up of these three eight-bit values. In fact, it is possible to create a color value directly from a 24-bit value by the use of casting.
// BBGGRR c = (Microsoft.SPOT.Presentation.Media.Color)0x00FF00;
The preceding line would set the color variable to bright green. Note that we used hexadecimal to express the color value because this makes it easier to isolate each byte in the value being created. This is the most efficient way to create a color value (although it presupposes a particular hardware arrangement of the colors that might not be available on the device you are using).
Even though you can select from a very wide range of colors, it is not necessarily the case that the hardware can display them. The SystemMetrics class provides the member ScreenColorDepth, which determines the number of colors that are supported by the hardware configuration you are using.
You can read the color of a pixel in the display by using the GetPixel method. This returns the color value at that position in the display.
// Include the media namespace using Microsoft.SPOT.Presentation.Media; ... Color pixelColor = myBitmap.GetPixel(0, 0)
This would set the variable pixelColor to the color of the pixel at the top left corner of the bitmap. Note that the Microsoft.SPOT.Presentation.Media namespace is at the very top of the program file, so you can use the Color class from that namespace without needing to use the fully qualified name.
The ColorUtility class also provides methods that will provide the red, green, and blue components from a given color.
byte r = ColorUtility.GetRValue(pixel); byte g = ColorUtility.GetGValue(pixel); byte b = ColorUtility.GetBValue(pixel);
The three bytes would each be set to the corresponding component value. There is also a method that can be used to set the color of a pixel in a bitmap.
myBitmap.SetPixel(0, 0, Colors.Red);
This would set the color of the pixel at the top left corner of the bitmap to red.