Building Graphical Interface Elements by Using the System.Drawing Namespace

Create a Windows form by using the Windows Forms Designer:

  • Build graphical interface elements by using the System.Drawing namespace.

The FCLs provide an advanced implementation of the Windows Graphics Design Interface (also known as GDI+). The GDI+ classes can be used to perform a variety of graphics-related tasks such as working with text, fonts, lines, shapes, and images. One of the main benefits of using GDI+ is that it allows you to work with Graphics objects without worrying about the specific details of the underlying platform. The GDI+ classes are distributed among four namespaces:

  • System.Drawing

  • System.Drawing.Drawing2D

  • System.Drawing.Imaging

  • System.Drawing.Text

All these classes reside in a file named System.Drawing.dll.

Understanding the Graphics Objects

The Graphics class is one of the most important classes in the System.Drawing namespace. It provides methods for doing various kinds of graphics manipulations. The Graphics class is a sealed class and cannot be further inherited (unlike the Form class, for example). The only way you can work with the Graphics class is through its instances (that is, Graphics objects). A Graphics object is a GDI+ drawing surface that you can manipulate by using the methods of the Graphics class.

When you look in the documentation of the Graphics class, you see that there is no constructor available for this class, and hence a Graphics object cannot be directly created. Despite this, there are at least four ways you can get a Graphics object:

  • Through the Graphics property of the PaintEventArgs argument passed to the Paint event handler of a control or a form. The Graphics object thus received represents the drawing surface of the object that was the source of the event.

  • By calling the CreateGraphics() method of a control or form.

  • By calling the Graphics.FromHwnd() method and passing it the handle of the current form.

  • By calling the static Graphics.FromImage() method. This method takes an image object and returns a Graphics object that corresponds to that image. You can then use this Graphics object to manipulate the image.

When you have a Graphics object available, you have access to a drawing surface. You can use this surface to draw lines, text, curves, shapes, and so on. But before you can draw, you must understand the Windows forms coordinate system, which is discussed in the following section.

Understanding the Windows Forms Coordinate System

The Windows Forms library treats a Windows form as an object that has a two-dimensional coordinate system, as shown in Figure 1.19. Therefore, when you write text on the form or put controls on the form, the position is identified by a set of points. A point is a pair of numbers that is generally represented as (x, y) where x and y, respectively, denote horizontal and vertical distance from the origin of the form. The origin of the form is the top-left corner of the client area of the form. (The client area is the inner area of the form that you get after excluding the space occupied by title bar, sizing borders, and menu, if any.) The point of the origin is treated as (0, 0). The value of x increases to the right of the point of origin, and the value of y increases below the point of origin.

Figure 1.19. The Windows Forms Coordinate system is a two-dimensional coordinate system.


Two structures are available to represent points in a program—Point and PointF. These structures each represent an ordered pair of values (x and y). Point stores a pair of int values, whereas PointF stores a pair of float values. In addition to these values, these structures also provide a set of static methods and operators to perform basic operation on points.

Table 1.8 summarizes all the structures defined in the System.Drawing namespace.

Table 1.8. System.Drawing Namespace Structures
StructureDescription
CharacterRangeSpecifies a range of character positions within a string.
ColorSpecifies a color structure that has 140 static properties, each representing the name of a color. In addition, it also has four properties—A, R, G, and B—which specify the value for the Alpha (level of transparency), Red, Green, and Blue portions of the color. A Color value can be created by using any of its three static methods: FromArgb(), FromKnownColor(), and FromName().
PointStores an ordered pair of integers, x and y, that defines a point in a two-dimensional plane. You can create a Point value by using its constructor. The Point structure also provides a set of methods and operators for working with points.
PointFSpecifies a float version of the Point structure.
RectangleStores the location and size of a rectangular region. You can create a Rectangle structure by using a Point structure and a Size structure. Point represents the top-left corner, and Size specifies the width and height from the given point.
RectangleFSpecifies a float version of the Rectangle structure.
SizeRepresents the size of a rectangular region with an ordered pair of width and height.
SizeFSpecifies a float version of the Size structure.

Drawing Text on a Form

The Graphics class provides a DrawString() method that can be invoked on a Graphics object to render a text string on the drawing surface. There are six different forms in which the DrawString() method can be used. In this section, I discuss three of them; the other three forms are the same, but with one extra argument of StringFormat type that specifies alignment and line spacing information.

STEP BY STEP

1.13 Drawing Text on a Form

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_13 and click the Open button.

2.
Open the Properties window. Search for the Paint event of the form, and double-click the row that contains the Paint event. Modify its event handler to look like this:

private void StepByStep1_13_Paint(object sender,
     System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;
    String str = String.Format(
      "Form Size is: Width={0}, Height={1}",
      Width, Height);
    grfx.DrawString(str, Font, Brushes.Black, 0, 0);
}

3.
Add the following code for the Main() method:

[STAThread]
static void Main()
{
    Application.Run(new StepByStep1_13());
}

4.
Set the form as the startup object. Run the project. The form displays a string of text in black, showing the width and height of the form. Figure 1.20 shows the result.

Figure 1.20. You can draw text on a Windows form by using the DrawString method of the Graphics class.



In Step by Step 1.13, why did I choose to write the code within an event handler? There are two reasons, the foremost being that the Paint event handler provides access to the Graphics object. Second, the Paint event is fired whenever the form is redrawn, which includes when the form is first shown and when the form is restored from its minimized state, as well as when the form is shown after a window overlapping it is removed. Therefore, a Paint event handler is an appropriate place to put the code that you want to be executed whenever a form is redrawn.

The code gets the Graphics object through the Graphics property of the PaintEventArgs argument of the Paint event handler. The next step is to call the DrawString() method to draw text on the form. The DrawString() method used in Step by Step 1.13 takes five arguments and has the following signature:

public void DrawString(
   string, Font, Brush, float, float);

The first argument, string, is the string to be displayed. I use the String.Format() method to format the string.

The second argument, Font, is the font of the string. In Step by Step 1.13 I chose to display the string by using the default font of the current form through the Font property.

The third parameter, Brush, is the type of brush. The Brushes enumeration provides a variety of Brush objects, each with a distinct color. I chose the Brushes.Black value to draw text in black.

The fourth and fifth properties, float and float, specify the x and y locations for the point that marks the start of the string on the form. Both of these values are required to be of float type. The 0 value that the code contains is implicitly converted to a float value.

EXAM TIP

Unicode Support and DrawString GDI+ and hence the Windows Forms library have full support for Unicode. This means that you can draw text in any language supported by the operating system.


You might have noticed that when you resize the form in Step by Step 1.13, the Paint event is not triggered. An obvious idea for improving this form is to have it dynamically reflect the size of the form as you resize it. What event should you handle to do that? The Resize event. Step by Step 1.14 explains how to do this.

STEP BY STEP

1.14 Using the Invalidate() Method

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_14 and click on the Open button.

2.
Follow steps 2 and 3 from Step by Step 1.13 to include the Paint event handler code and Main() method to run the form StepByStep1_14.

3.
Open the Properties window of the form StepByStep1_14. Search for the Resize event, and double-click on the row that contains the Resize event. Modify its event handler so that it looks like this:

private void StepByStep1_14_Resize(
   object sender, System.EventArgs e)
{
    // Call the Invalidate method
    Invalidate();
}

4.
Set the form as the startup object. Run the project and notice that the form constantly modifies the text as it is resized.


After you complete Step by Step 1.14, the program works as desired. What's the deal with the Invalidate() method? The Invalidate() method causes the paint message to be sent to the form.

As a result, the Paint event handler is called. So this handy method can be called whenever the code in the Paint event handler needs to be executed. In Step by Step 1.14, the code makes a call to the Invalidate() method whenever the form is resized. The Invalidate() method is available in various forms, and you can refresh a specific portion of a form by using one of these forms.

EXAM TIP

Invalidate() Method Calls When you call the Invalidate() method without any parameters, the Paint event is called for the entire area. If only a particular portion of the control needs to be refreshed, then calling Invalidate() for the entire area is rather taxing on application performance. In such a case you should call Invalidate() with a Rectangle parameter that specifies the portion of the control that you are interested in refreshing.


Given the frequent requirement of calling Paint whenever Resize is fired, the Windows Forms library designers created a useful property: ResizeRedraw. This is a protected property that the Form class inherits from the Control class. When ResizeRedraw is set to true, it instructs a control (or a form, in this case) to redraw itself when it is resized. Its default value is false. Step by Step 1.15 shows how to use ResizeRedraw.

STEP BY STEP

1.15 Using the ResizeRedraw Property

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_15 and click the Open button.

2.
Follow steps 2 and 3 from Step by Step 1.13 to include the Paint event handler code and Main() method to run the form StepByStep1_15.

3.
Switch to the code view. Modify the constructor of the form so that the modified version looks like this:

public StepByStep1_15()
{
    //
    // Required for Windows Form Designer support
    //
    InitializeComponent();

    // Paint when resized
    this.ResizeRedraw = true;
}

4.
Run the project and notice that the form paints its drawing surface whenever you resize the form (just as it does in Step by Step 1.14, although the implementation is different).


The form's constructor is a good place to set the ResizeRedraw property. You could alternatively write it inside the Main() method itself.

As one more enhancement to Step by Step 1.15, you can center the text programmatically within the form. To do so, first you need to find the coordinates of the center of the form. You can find the horizontal distance by dividing the width of the client area (ClientSize.Width) by 2, and you can find the vertical distance by dividing the height of the client area (ClientSize.Height) by 2. The ClientSize properties give you access to a Size structure that represents the size of the client area of the form. But this does not really center the text onscreen because it simply causes the text to start from the center, and depending on how long it is, it might appear toward the right of the center. You need to adjust the coordinates of the center point according to the size of the string. Keep in mind that the size of the string can vary depending on what font you use for the text. A safe way to determine string size is to use the MeasureString() method of the Graphics object, as shown in the following code segment:

SizeF stringSize = grfx.MeasureString(str, Font);

You can then calculate the modified coordinates for placing the string as x = (ClientSize.WidthstringSize.Width)/2 and y = (ClientSize.HeightstringSize.Height)/2.

There is an alternative approach, however. You can use the StringFormat object in the following signature of the DrawString() method:

public void DrawString(
   string, Font, Brush, PointF, StringFormat);

The StringFormat argument lets you specify the text alignment and spacing options for the text. Step by Step 1.16 uses this form of DrawString() to center text onscreen.

STEP BY STEP

1.16 Drawing Text on a Form

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_16 and click the Open button.

2.
Open the Properties window of the form. Search for the Paint event, and double-click the row that contains the Paint event. Modify its event handler so that it looks like this:

private void StepByStep1_16_Paint(object sender,
    System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;
    String strText = String.Format(
        "Form Size is: Width={0}, Height={1}",
        Width, Height);
    PointF pt = new PointF(ClientSize.Width/2,
        ClientSize.Height/2);

    // Set the horizontal and vertical alignment
    //using StringFormat object
    StringFormat strFormat = new StringFormat();
    strFormat.Alignment = StringAlignment.Center;
    strFormat.LineAlignment = StringAlignment.Center;

    // Create Font and Brush objects
    Font fntArial = new Font("Arial", 12);
    Brush brushColor = new SolidBrush(this.ForeColor);
    // Call the DrawString method
    grfx.DrawString(
       strText, fntArial, brushColor, pt, strFormat);
}

3.
Modify the constructor of the form so that the modified version looks like this:

public StepByStep1_16()
{
    // Default Code in the constructor
    // Paint when resized
    this.ResizeRedraw = true;
}

4.
Add the following code for the Main() method:

[STAThread]
static void Main()
{
    Application.Run(new StepByStep1_16());
}

5.
Set the form as the startup object. Run the project and resize the form. Notice that the text is displayed in the center of the form.


The code begins by calculating the center coordinates of the form. When you have the coordinates of the center, you want the string to be horizontally centered at that point. Calling StringAlignment.Center does this job. StringAlignment is an enumeration that is available in the System.Drawing namespace that specifies the location of the alignment of the text.

By default, when the DrawString() method draws a string, it aligns the top of the string with its x-coordinate value. This does not make much difference if the height of the text itself is not great, but as you increase the size of the font, text begins to hang down, starting from the x-axis. To center the text vertically within its own line, you can set the LineAlignment property of the StringFormat object to StringAlignment.Center.

Note the use of Font and Brush objects in Step by Step 1.16. The code creates a new Font object and specifies a font name and size. I recommend that you change its value and experiment with it. Rather than use the brush specified by the Brushes.Black value, the code in Step by Step 1.16 creates a Brush object that takes the value of its color from the current form's ForeColor property. If you change the ForeColor property of the form by using the Properties window, the change is automatically reflected here. Using a brush based on the ForeColor property of the form is a good idea as compared to using an absolute value such as Brushes.Black for a brush. For example, if the form designer has set the BackColor property of the form to black and the ForeColor property to white, text drawn using Brushes.Black would not be visible, but the brush made from the ForeColor property would be visible.

Drawing Shapes

The Graphics class allows you to draw various graphical shapes such as arcs, curves, pies, ellipses, rectangles, images, paths, and polygons. Table 1.9 lists some important drawing methods of the Graphics class.

Table 1.9. Some Important Drawing Methods of the Graphics Class
MethodDescription
DrawArc()Draws an arc that represents a portion of an ellipse
DrawBezier()Draws a Bézier curve defined by four points
DrawBeziers()Draws a series of Bézier curves
DrawClosedCurve()Draws a closed curve defined by an array of points
DrawCurve()Draws a curve defined by an array of points
DrawEllipse()Draws an ellipse defined by a bounding rectangle specified by a pair of coordinates, a height, and a width
DrawIcon()Draws the image represented by the specified Icon object at the given coordinates
DrawImage()Draws an Image object at the specified location, preserving its original size
DrawLine()Draws a line that connects the two points
DrawLines()Draws a series of line segments that connect an array of points
DrawPath()Draws a GraphicsPath object
DrawPie()Draws a pie shape defined by an ellipse and two radial lines
DrawPolygon()Draws a polygon defined by an array of points
DrawRectangle()Draws a rectangle specified by a point, a width, and a height
DrawRectangles()Draws a series of rectangles
DrawString()Draws the given text string at the specified location, with the specified Brush and Font objects

In Step by Step 1.17 you use some of the methods shown in Table 1.9 to draw shapes on a form's surface.

STEP BY STEP

1.17 Using the Draw Methods of the Graphics Class

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_17 and click the Open button.

2.
Open the Properties window. Search for the Paint event, and double-click the row that contains the Paint event. You are taken to the code view.

3.
On the top of the code view, along with the list of other using directives, add the following line of code:

using System.Drawing.Drawing2D;

4.
Modify the code in the Paint event handler to look like this:

private void StepByStep1_17_Paint(object sender,
   System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;
          // Set the Smoothing mode
          // to SmoothingMode.AntiAlias
    grfx.SmoothingMode = SmoothingMode.AntiAlias;
          // Create Pen objects
    Pen penYellow = new Pen(Color.Blue, 20);
    Pen penRed = new Pen(Color.Red, 10);
    // Call Draw methods
    grfx.DrawLine(Pens.Black, 20, 130, 250, 130);
    grfx.DrawEllipse(penYellow, 20, 10, 100, 100);
    grfx.DrawRectangle(penRed, 150, 10, 100, 100);
}

5.
Add the following code to insert the Main() method:

[STAThread]
static void Main()
{
    Application.Run(new StepByStep1_17());
}

6.
Set the form as the startup object. Run the project, and you see the form as displayed in Figure 1.21.

Figure 1.21. You can call Draw methods of the Graphics class to draw various graphic shapes.



The Draw methods used in Step by Step 1.17 take five arguments:

  • The first argument of each method is the Pen object that is used to draw the shape. There are several ways you can create a Pen object. The simplest way is to use a readymade Pen object from the Pens class. Or you can create a Pen object by using the Pen class constructor. Table 1.10 lists the different pen-related classes that are available in the System.Drawing namespace.

  • The second and third arguments are the x- and y-coordinates of the upper-left corner where the desired shape is to be drawn.

  • The fourth and fifth parameters indicate the width and height of the desired shape to be drawn. In the case of DrawLine, these indicate the x- and y-coordinates of the ending point of the line drawn.

Table 1.10. Pen-Related Classes in the System.Drawing Namespace
ClassDescription
PenDefines an object used to draw lines and curves.
PensProvides 140 static properties, each representing a pen of a color supported by Windows Forms.
SystemPensProvides a set of static properties, each named after a Windows display element such as ActiveCaption, WindowText, and so on. Each of these properties returns a Pen object with a width of 1.

The reason you must include a reference to the System.Drawing.Drawing2D namespace in the program shown in Step by Step 1.17 is that you are using an enumeration named SmoothingMode. This enumeration class is defined in the namespace System.Drawing.Drawing2D, so a reference to the namespace must be present in the program if the C# compiler is to uniquely identify it.

The Graphics object has a property named SmoothingMode that can take the values of the SmoothingMode enumeration type. Table 1.11 summarizes these values. The SmoothingMode property specifies the quality of rendering. The Windows Forms library supports antialiasing, which produces text and graphics that appear to be smooth.

NOTE

Antialiasing Antialiasing is a technique for rendering images where partially transparent pixels are drawn close to the opaque pixels present at the edges of a drawing. This actually makes the edges kind of fuzzy, but this effect makes the edges appear smoother to human eyes than the original form. Because there are extra efforts involved in antialiasing, it makes rendering of graphics slower than not using antialiasing.


Table 1.11. SmoothingMode Enumeration Members
Member NameDescription
AntiAliasSpecifies an antialiased rendering.
DefaultSpecifies no antialiasing. Same as None.
HighQualitySpecifies a high-quality, low-performance rendering. Same as AntiAlias.
HighSpeedSpecifies a high-performance, low-quality rendering. Same as None.
InvalidSpecifies an invalid mode, raises an exception.
NoneSpecifies no antialiasing.

In addition to the Draw methods, the Graphics class also provides a variety of Fill methods (see Table 1.12). You can use these methods to draw a solid shape on a form.

Table 1.12. Fill Methods of the Graphics Class
Method NameDescription
FillClosedCurve()Fills the interior of a closed curve defined by an array of points
FillEllipse()Fills the interior of an ellipse defined by a bounding rectangle
FillPath()Fills the interior of a GraphicsPath object
FillPie()Fills the interior of a pie section defined by an ellipse and two radial lines
FillPolygon()Fills the interior of a polygon defined by an array of points
FillRectangle()Fills the interior of a rectangle specified by a point, a width, and a height
FillRectangles()Fills the interiors of a series of rectangles
FillRegion()Fills the interior of a Region object

STEP BY STEP

1.18 Using the Fill Methods of the Graphics Class

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_18 and click the Open button.

2.
Open the Properties window of the form. Search for the Paint event, and double-click the row that contains the Paint event. You are taken to the code view.

3.
Modify the code in the Paint event handler to look like this:

private void StepByStep1_18_Paint(object sender,
    System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;
    // Create Brush objects
    Brush brushRed = new SolidBrush(Color.Red);
    Brush brushYellow = new SolidBrush(
        Color.FromArgb(200, Color.Yellow));
    // Call Fill methods
    grfx.FillEllipse(brushRed, 20, 10, 80, 100);
    grfx.FillRectangle(brushYellow, 60, 50, 100, 100);
}

4.
Add the following code to insert the Main() method:

[STAThread]
static void Main()
{
   Application.Run(new StepByStep1_18());
}

5.
Set the form as the startup object. Run the project. An overlapping red ellipse and yellow rectangle appear on the form, as shown in Figure 1.22.

Figure 1.22. You can use Fill methods of the Graphics class to draw solid shapes.



The syntax of the Fill methods is somewhat similar to that of corresponding Draw methods. The only difference is that the Fill methods use a Brush object to fill a drawing object with a color.

Creating the yellow brush in Step by Step 1.18 looks interesting. While creating this color, you do an “alpha-blending” with the yellow color, to get a kind of transparent yellow color that is used to produce an overlay effect.

You use a SolidBrush object in Step by Step 1.18 to fill shapes. Other types of brushes can be used to create fancy filling effects; Table 1.13 lists them.

Table 1.13. Types of Brushes in the System.Drawing and System.Drawing.Drawing2D Namespaces
ClassDescription
BrushIs an abstract base class that is used to create brushes such as SolidBrush, TextureBrush, and LinearGradientBrush. These brushes are used to fill the interiors of graphical shapes such as rectangles, ellipses, pies, polygons, and paths.
BrushesProvides 140 static properties, one for the name of each color supported by Windows forms.
HatchBrushAllows you to fill the region by using one pattern from a large number of patterns available in the HatchStyle enumeration.
LinearGradientBrushIs used to create two-color gradients and multicolor gradients. By default the gradient is a linear gradient that moves from one color to another color along the specified line.
SolidBrushDefines a brush of a single color. Brushes are used to fill graphics shapes, such as rectangles, ellipses, pies, polygons, and paths.
SystemBrushesProvides a set of static properties, each named after a Windows display element, such as ActiveCaption, WindowText, and so on. Each of these properties returns a SolidBrush object that represents the color for its matching Windows display element.
TextureBrushA class that contains properties for the Brush object that use images to fill the interior of shapes.

STEP BY STEP

1.19 Using Different Brush Types

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_19 and click the Open button.

2.
Open the Properties window. Search for the Paint event, and double-click the row that contains the Paint event. You are taken to the code view.

3.
On the top of the code view, along with the list of other using directives, add the following lines of code:

using System.Drawing.Drawing2D;

4.
Modify the code in the Paint event handler so that it looks like this:

private void StepByStep1_19_Paint(object sender,
    System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;

    // Create a HatchBrush object
    // Call FillEllipse method by passing
    // the created HatchBrush object
    HatchBrush hb = new HatchBrush(
        HatchStyle.HorizontalBrick,
       Color.Blue, Color.FromArgb(100, Color.Yellow));
    grfx.FillEllipse(hb, 20, 10, 100, 100);

    // Create a TextureBrush object
    // Call FillEllipse method by passing the
    // created TextureBrush object
    Image img = new Bitmap("sunset.jpg");
    Brush tb = new TextureBrush(img);
    grfx.FillEllipse(tb, 150, 10, 100, 100);

    // Create a LinearGradientBrush object
    // Call FillEllipse method by passing
    // the created LinearGradientBrush object
    LinearGradientBrush lb = new LinearGradientBrush(
        new Rectangle(80, 150, 100, 100),
        Color.Red, Color.Yellow,
           LinearGradientMode.BackwardDiagonal);
    grfx.FillEllipse(lb, 80, 150, 100, 100);
}

5.
Add the following code to insert the Main() method:

[STAThread]
static void Main()
{
    Application.Run(new StepByStep1_19());
}

6.
Set the form as the startup object. Run the project. Notice that ellipses filled in various styles are displayed in the form, as shown in Figure 1.23.

Figure 1.23. You can create fancy objects by using different brush types.



In Step by Step 1.19 you use three different Brush objects. The TextureBrush class is part of the System.Drawing namespace, and the other two classes (HatchBrush and LinearGradientBrush) are members of the System.Drawing.Drawing2D namespace.

Using HatchBrush, you filled the ellipse with the HatchStyle named HorizontalBrick. The TextureBrush class uses an image to fill the interior of a shape, and in Step by Step 1.19, the image is assumed to be in the same directory as the .exe file. If you have the image in some other directory, you need to change the path in the Bitmap constructor. The Bitmap name is a bit misleading, as it is actually capable of creating images from a variety of image formats, including BMP, GIF, JPG, and PNG.

In Step by Step 1.19 the code sets the gradient direction from the upper-right corner to the lower-left corner of the rectangle encapsulating the ellipse. Table 1.14 lists the enumeration values for LinearGradientMode.

Table 1.14. LinearGradientMode Enumeration Values
Member NameDescription
BackwardDiagonalSpecifies a gradient from upper-right to lower-left
ForwardDiagonalSpecifies a gradient from upper-left to lower-right
HorizontalSpecifies a gradient from left to right
VerticalSpecifies a gradient from top to bottom

Working with Images

The System.Drawing.Image class provides the basic functionality for working with images. However, the Image class is abstract, which means you can create an instance of it in your class. Instead of using the Image class directly, you can use the following classes that implement the Image class functionality:

  • Bitmap This class is used to work with graphic files that store information in pixel-based data such as BMP, GIF, and JPEG formats.

  • Icon This class creates a small bitmap that represents an Windows icon.

  • MetaFile This class contains embedded bitmaps and/or sequences of binary records that represent a graphical operation such as drawing a line.

Step by Step 1.20 shows how to do basic operations with the Bitmap class.

STEP BY STEP

1.20 Creating and Rendering Images

1.
Open the project 316C01. In the Solution Explorer right-click the project name and select Add Windows Form from the context menu. Name the new form StepByStep1_20 and click the Open button.

2.
Open the Properties window. Search for the Paint event, and double-click the row that contains the Paint event. You are taken to the code view.

3.
On the top of the code view, along with the list of other using directives, add the following lines of code:

using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

4.
Modify the code in the Paint event handler to look like this:

private void StepByStep1_20_Paint(object sender,
    System.Windows.Forms.PaintEventArgs e)
{
    Graphics grfx = e.Graphics;
    grfx.DrawImage(new Bitmap("SampleImage.png"),
        ClientRectangle);
}

5.
Add the following code after the event handling code from step 4:

[STAThread]
static void Main()
{
    // Create a Bitmap object
    Bitmap bmp = new Bitmap(
        800,600,PixelFormat.Format32bppArgb);
    // Create a Graphics object using FromImage method
    Graphics grfx = Graphics.FromImage(bmp);
    // Call the Fill Rectangle method
    // to create an outer rectangle
    grfx.FillRectangle(new SolidBrush(Color.White),
        new Rectangle(0,0,800,600));
    // Create Font and RectangleF object
    Font fntText = new Font("Verdana", 20);
    RectangleF rect = new RectangleF(
       100, 100, 250, 300);
    // Fill the InnerRectangle
    grfx.FillRectangle(
        new SolidBrush(Color.AliceBlue), rect);
    // Add the text to the Inner Rectangle
    grfx.DrawString("Sample Text", fntText,
      new SolidBrush(Color.Blue), rect);
    // Draw a closed curve
    Pen penBlack = new Pen(Color.Black, 20);
    penBlack.DashStyle = DashStyle.Dash;
    penBlack.StartCap = LineCap.Round;
    penBlack.EndCap = LineCap.Round;
    grfx.DrawClosedCurve(penBlack, new Point[] {
                         new Point(50, 50),
                         new Point(400, 50),
                         new Point(400, 400),
                         new Point(50, 400)});
    // Save the newly created image file
    bmp.Save("SampleImage.png", ImageFormat.Png);
    Application.Run(new StepByStep1_20());
}

6.
Set the form as the startup object. Run the project. The code should create an image and render it in the form, as shown in Figure 1.24.

Figure 1.24. You can use the Bitmap class to work with a variety of image formats.



In Step by Step 1.20 you first create an image and then render it on the form's surface. The image creation code is written in the Main() method, which means it is executed before the application creates the Form object. Three key steps are related to image manipulation:

1.
You need to create a Bitmap object that can be used to work on images. The code for this creates the object by specifying its size in pixels and also specifying a format value from the PixelFormat enumeration, which belongs to the System.Drawing.Imaging namespace. The value Format32bppArgb specifies that there are 32 bits of data associated with each pixel in the image. Out of these 32 bits, 8 bits each are used for the alpha, red, green, and blue components of the pixel.

2.
You need to get a Graphics object from the Bitmap object. This Graphics object can be used to draw on the surface of the drawing.

3.
You need to call the Save() method on the Bitmap object. This method supports a variety of formats for saving graphics; these formats are available as static public properties of the ImageFormat class. The ImageFormat class is a member of the System.Drawing.Imaging namespace. Some of the possible properties are Bmp, Gif, Icon, Jpeg, Png, Tiff, and Wmf.

The rest of the code in Step by Step 1.20 draws a piece of text and a curved line on the image before saving it. Note the various properties of the Pen object that are used in this program. The code uses the customized Pen object to create a boundary around the image. Table 1.15 summarizes some important properties of the Pen class.

Table 1.15. Some Important Properties of the Pen Class
PropertyDescription
AlignmentSpecifies the alignment for the Pen object
BrushSpecifies a Brush object that determines the attributes of the Pen object
ColorSpecifies the color of the Pen object
DashCapSpecifies the cap style used at the end of the dashes that make up dashed lines
DashPatternSpecifies the array of custom dashes and spaces
DashStyleSpecifies the style used for dashed lines
EndCapSpecifies the cap style used at the end of lines
LineJoinSpecifies the join style for the ends of two consecutive lines
PenTypeSpecifies the style of lines
StartCapSpecifies the cap style used at the beginnings of lines
WidthSpecifies the width of the Pen object

GUIDED PRACTICE EXERCISE 1.3

You are a Windows developer for SpiderWare, Inc. The Windows application you are working on should have a form that allows users to create new designs for Spider-Webs. The requirement itself is simple: The form must have a white background, where users can design using a thin black pen. Users often make mistakes while they are designing, so there should be a mechanism to erase part of the design. Users say that they will be comfortable using the left mouse button for drawing and the right mouse button for erasing. You also noted that users of the application all have high-end machines, and they want sharper-looking designs.

How would you design such a form?

You should try working through this problem on your own first. If you get stuck, or if you'd like to see one possible solution, follow these steps:

1.
Open the project 316C01. Add a Windows form with the name GuidedPracticeExercise1_3 to this project.

2.
Open the Properties window for the form. Change the form's BackColor property to White.

3.
Look for the event named MouseMove and double-click it. This inserts a MouseMove event handler for you and switches you to the code view. In the code view, add the following statement at the top of the program:

using System.Drawing.Drawing2D;

4.
Before the MouseMove event handler code add the following line:

Point ptPrevPosition = new Point(-1, -1);

5.
Modify the MouseMove event handler to look like this:

private void GuidedPracticeExercise1_3_MouseMove(
  object sender, System.Windows.Forms.MouseEventArgs e)
{
    if(ptPrevPosition.X == -1)
    {
        // Set the previous position x-y co-ordinate
        // to the current x-y co-ordinate
        ptPrevPosition = new Point(e.X, e.Y);
    }
    Point ptCurrPosition = new Point(e.X,e.Y);
    // Get the Graphics object by calling
    // Graphics.FromHwnd() method
    Graphics g = Graphics.FromHwnd(this.Handle);
    g.SmoothingMode = SmoothingMode.AntiAlias;
    // Check if the left mouse button is pressed
    if(e.Button == MouseButtons.Left)
    {
        // Draw a line from the previous position to
        // current position using Black color
        g.DrawLine(new Pen(Color.Black),
            ptPrevPosition, ptCurrPosition);
    }
    // Check whether right mouse button is pressed
    else if(e.Button == MouseButtons.Right)
    {
        // Draw a line from the previous position to
        // current position using Form's BackColor
        g.DrawLine(new Pen(this.BackColor, 4),
           ptPrevPosition, ptCurrPosition);
    }
    // Set the Previous position to current position
    ptPrevPosition = ptCurrPosition;
}

6.
Insert the following Main() method just after the event handling code:

[STAThread]
static void Main()
{
    Application.Run(new GuidedPracticeExercise1_3());
}

7.
Set the form as the startup object and execute the program.

If you have difficulty following this exercise, review the sections “Event Handling” and “Drawing Shapes.” The text and examples presented in those sections should help you relearn this material. After doing that review, try this exercise again.


REVIEW BREAK

  • Windows forms follow a two-dimensional coordinate system. A point is an addressable location in this coordinate system.

  • The Graphics object gives you access to a drawing surface. You can use it to draw lines, text, curves, and a variety of shapes.

  • The ResizeRedraw property, when set to true, instructs the form to redraw itself when it is resized. It's a good programming practice to design forms that resize their contents based on their size. The Resize event of a form can also be used to program the resizing logic.

  • The Graphics class provides a set of Draw methods that can be used to draw shapes such as rectangles, ellipses, and curves on a drawing surface. The Graphics class also provides a set of Fill methods that can be used to create solid shapes.

  • An object of the Bitmap class gives you access to image manipulation. The System.Drawing namespace classes can understand a variety of image formats.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.98.249