The GDI+Painter Application

Almost every chapter of this book will show a real-world example to illustrate the concepts discussed in it. In this chapter we create an application, GDI+Painter, that you can use to draw and fill simple graphics objects. If you wish, you can add more functionality to the application. Once you are done drawing graphics shapes, the program allows you to save your drawing in bitmap format. You can modify the program to save a drawing in .jpeg or .gif format.

The program is a Windows Forms application and looks like Figure 3.42. It has three draw buttons (line, ellipse, and rectangle) and two fill buttons (rectangle and ellipse). The Save Image button allows you to save the image.

Figure 3.42. The GDI+Painter application

graphics/03fig42.gif

Click on a button and the program draws the selected item on the form. Here's how it works:

First we define some private class-level variables:


 
// Variables
private Bitmap bitmap = null;
private Bitmap curBitmap = null;
private bool dragMode = false;
private int drawIndex = 1;
private int curX, curY, x, y;
private int diffX, diffY;
private Graphics curGraphics;
private Pen curPen;
private SolidBrush curBrush;
private Size fullSize;

 

Note

Please download GDI+Painter application source code from online (www.awprofessional.com/titles/0321160770).

The next step is to initialize objects. On the form-load event handler, we create a bitmap and a Graphics object from the bitmap, which represents the entire form. We set its background color to the form's background color by calling the Graphics.Clear method. We also create a Pen object and a Brush object when the form loads. Listing 3.31 gives the form-load event handler code.

Listing 3.31 The form-load event handler

private void Form1_Load(object sender,
 System.EventArgs e)
{
 // Get the full size of the form
 fullSize = SystemInformation
 .PrimaryMonitorMaximizedWindowSize;
 // Create a bitmap using full size
 bitmap = new Bitmap(fullSize.Width,
 fullSize.Height);
 // Create a Graphics object from Bitmap
 curGraphics = Graphics.FromImage(bitmap);
 // Set background color as form's color
 curGraphics.Clear(this.BackColor);
 // Create a new pen and brush as
 // default pen and brush
 curPen = new Pen(Color.Black);
 curBrush = new SolidBrush(Color.Black);
}

When we click on a button, we find out which button was selected and save it in the drawIndex variable. Listing 3.32 gives code for the button click event handler for all buttons.

Listing 3.32 Saving a selected button

private void LineDraw_Click(object sender,
 System.EventArgs e)
 {
 drawIndex = 1;
 }

 private void RectDraw_Click(object sender,
 System.EventArgs e)
 {
 drawIndex = 2;
 }

 private void EllipseDraw_Click(object sender,
 System.EventArgs e)
 {
 drawIndex = 3;
 }
 private void FilledEllipse_Click(object sender,
 System.EventArgs e)
 {
 drawIndex = 5;
}

When we start drawing on the form, we save the starting point on the mouse-down events and the ending point on the mouse-up events (see Listing 3.33). From these two points we can determine the area of the rectangle we're trying to draw. We use this rectangle in draw and fill methods.

On a mouse-move event, we calculate the difference between the ending and starting points that are used to draw the rectangle. Notice also that on mouse down we set dragMode to true, and on mouse up we set dragMode to false. On the basis of the area covered by user selection, we draw or fill objects on mouse up, which gives the user a visible drawing effect. You will also see the RefreshFormBackground method, which we will discuss shortly.

Listing 3.33 The mouse-down event handler

private void Form1_MouseDown(object sender,
 System.Windows.Forms.MouseEventArgs e)
{
 // Store the starting point of
 // the rectangle and set the drag mode
 // to true
 curX = e.X;
 curY = e.Y;
 dragMode = true;
}

private void Form1_MouseMove(object sender,
 System.Windows.Forms.MouseEventArgs e)
{
 // Find out the ending point of
 // the rectangle and calculate the
 // difference between starting and ending
 // points to find out the height and width
 // of the rectangle
 x = e.X;
 y = e.Y;
 diffX = e.X - curX;
 diffY = e.Y - curY;
 // If dragMode is true, call refresh
 // to force the window to repaint
 if (dragMode)
 {
 this.Refresh();
 }
}

private void Form1_MouseUp(object sender,
 System.Windows.Forms.MouseEventArgs e)
{
 diffX = x - curX;
 diffY = y - curY;
 switch (drawIndex)
 {
 case 1:
 {
 // Draw a line
 curGraphics.DrawLine(curPen,
 curX, curY, x, y);
 break;
 }
 case 2:
 {
 // Draw an ellipse
 curGraphics.DrawEllipse(curPen,
 curX, curY, diffX, diffY);
 break;
 }
 case 3:
 {
 // Draw a rectangle
 curGraphics.DrawRectangle(curPen,
 curX, curY, diffX, diffY);
 break;
 }
 case 4:
 {
 // Fill the rectangle
 curGraphics.FillRectangle(curBrush,
 curX, curY, diffX, diffY);
 break;
 }
 case 5:
 {
 // Fill the ellipse
 curGraphics.FillEllipse(curBrush,
 curX, curY, diffX, diffY);
 break;
 }
 }
 // Refresh
 RefreshFormBackground();
 // Set drag mode to false
 dragMode = false;
}

Now we add code to the form's paint event handler, which draws and fills the object. Listing 3.34 gives the code for the OnPaint method.

Listing 3.34 The OnPaint method

private void Form1_Paint(object sender,
 System.Windows.Forms.PaintEventArgs e)
 {

 Graphics g = e.Graphics;
 // If dragMode is true, draw the selected
 // graphics shape
 if (dragMode)
 {
 switch (drawIndex)
 {
 case 1:
 {
 g.DrawLine(curPen, curX, curY, x, y);
 break;
 }
 case 2:
 {
 g.DrawEllipse(curPen,
 curX, curY, diffX, diffY);
 break;
 }
 case 3:
 {
 g.DrawRectangle(curPen,
 curX, curY, diffX, diffY);
 break;
 }
 case 4:
 {
 g.FillRectangle(curBrush,
 curX, curY, diffX, diffY);
 break;
 }
 case 5:
 {
 g.FillEllipse(curBrush,
 curX, curY, diffX, diffY);
 break;
 }
 }
 }
}

Here's a little trick. You may have noticed that we used the RefreshFormBackground method. This method sets the current drawing as the background of the form. Listing 3.35 gives code for the method.

Listing 3.35 The RefreshFormBackground method

private void RefreshFormBackground()
{
 curBitmap = bitmap.Clone(
 new Rectangle(0, 0, this.Width, this.Height),
 bitmap.PixelFormat);
 this.BackgroundImage = curBitmap;
}

The Save Image button allows us to save the image by simply calling the Save method of Bitmap. The Save method takes a file name and format. We use SaveFileDialog to select the file name. Listing 3.36 gives code for the Save Image button.

Listing 3.36 The Save Image button click handler

private void SaveBtn_Click(object sender,
 System.EventArgs e)
{
 // Save file dialog
 SaveFileDialog saveFileDlg = new SaveFileDialog();
 saveFileDlg.Filter =
 "Image files (*.bmp)|*.bmp|All files (*.*)|*.*" ;
 if(saveFileDlg.ShowDialog() == DialogResult.OK)
 {
 // Create bitmap and call Save method
 // to save it
 Bitmap tmpBitmap = bitmap.Clone
 (new Rectangle(0, 0,
 this.Width, this.Height),
 bitmap.PixelFormat);
 tmpBitmap.Save(saveFileDlg.FileName,
 ImageFormat.Bmp);
 }
}

In the end we release all objects, which we can do on the form-closed event (see Listing 3.37).

Listing 3.37 The form-closed event handler

private void Form1_Closed(object sender, System.EventArgs e)
{
 // Dispose of all public objects
 curPen.Dispose();
 curBrush.Dispose();
 curGraphics.Dispose();
}

In Chapter 4 we will add functionality to select different pens and brushes to draw and fill graphics shapes.

GDI+: The Next-Generation Graphics Interface

Your First GDI+ Application

The Graphics Class

Working with Brushes and Pens

Colors, Fonts, and Text

Rectangles and Regions

Working with Images

Advanced Imaging

Advanced 2D Graphics

Transformation

Printing

Developing GDI+ Web Applications

GDI+ Best Practices and Performance Techniques

GDI Interoperability

Miscellaneous GDI+ Examples

Appendix A. Exception Handling in .NET



GDI+ Programming with C#
GDI+ Programming with C#
ISBN: 073561265X
EAN: N/A
Year: 2003
Pages: 145

Flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net