Title: Draw in a Paint event handler in C#
Using images and drawing in the Paint event handler are the two most common ways to display graphics. Drawing in the Paint event handler is easy, but there are a couple of things you should keep in mind when you do so.
First, the e.Graphics parameter gives you the Graphics object on which you should draw. Don't create your own Graphics object, for example by using the CreateGraphics method. Otherwise the e.Graphics parameter will draw over anything you draw on a Graphics object that you create.
Second, don't set the form's BackgroundImage property inside the Paint event handler. Not only is that confusing, but it also makes the form raise its Paint event again so you get a never-ending series of Paint events. Similarly if you're handling a PictureBox control's Paint event handler, don't set the control's Image or BackgroundImage property.
Either draw in the Paint event handler or use an image but not both.
Third, you should generally assume that the current image contains results of previous drawings. For example, when you enlarge a form, it raises its Paint event but it clips the drawing area so new drawing can only occur on parts of the form that are newly exposed. If you're drawing a 100×100 circle in the upper left corner, there's no problem.
In contrast, suppose you're drawing an ellipse that fills the form. (As this example does.) In that case, the new ellipse doesn't exactly match up with the previous one when you resize the form. That means parts of the previous drawing may still be visible.
You can make a form automatically redraw itself whenever it resizes by setting its ResizeRedraw property to true when the form loads. This example does that in the following code.
// Redraw on resize.
private void Form1_Load(object sender, EventArgs e)
{
ResizeRedraw = true;
}
To see why this is important, comment out that line of code and see what happens.
Similarly you should assume pieces of the old image remain if you're drawing in a PictureBox. Unfortunately the PictureBox doesn't have a ResizeRedraw property. To redraw a PictureBox when it resizes, catch its Resize event and refresh the control as in the following code.
private void picEllipse_Resize(object sender, EventArgs e)
{
picEllipse.Refresh();
}
Calling the control's Refresh method makes it raise its Paint event so the event handler can draw whatever is needed. Calling Refresh also clears the clipping rectangle so the entire PictureBox is redrawn.
This example uses the following Paint event handler to draw an ellipse on the form.
// Draw an ellipse.
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(10, 10,
this.ClientSize.Width - 20,
this.ClientSize.Height - 20);
e.Graphics.FillEllipse(Brushes.Yellow, rect);
using (Pen thick_pen = new Pen(Color.Red, 5))
{
e.Graphics.DrawEllipse(thick_pen, rect);
}
}
The code clears the Graphics object to give it a white background and sets SmoothingMode to AntiAlias. It then makes a Rectangle to define where the ellipse will go. Using the same Rectangle to fill and outline the ellipse guarantees that the two line up correctly. It fills the ellipse with yellow and then outlines it with a thick red pen.
The program uses the following code to draw an ellipse on its PictureBox when that control raises a Paint event.
private void picEllipse_Paint(object sender, PaintEventArgs e)
{
e.Graphics.Clear(Color.White);
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
Rectangle rect = new Rectangle(10, 10,
picEllipse.ClientSize.Width - 20,
picEllipse.ClientSize.Height - 20);
e.Graphics.FillEllipse(Brushes.Pink, rect);
using (Pen thick_pen = new Pen(Color.Blue, 5))
{
e.Graphics.DrawEllipse(thick_pen, rect);
}
}
This code is very similar to the code that draws an ellipse on the form.
Download the example to experiment with it and to see additional details.
|