Snake - using the GDI+
Written by Mike James   
Tuesday, 04 August 2009
Article Index
Snake - using the GDI+
Getting started
Persistent graphics
Snake

Paint

If you have tried any of the examples you will have noticed that what you draw isn’t persistent in the sense that as soon as something covers up the form what you drew is gone.

Another way of saying this is that the GDI+ doesn't create retained mode graphics - whereas WPF does work in retained mode and what you draw persists.

The reason for this is that that a Windows drawing surface isn’t automatically saved. You draw to it and then something else can draw over it. If you want to restore what you drew then you have to re-draw it when the system tells you to.

This is what the Paint event and its handler are all about – it is called when the form needs re-painting and this is where you should put any graphics code that needs to have a persistent effect.

The easiest way of creating an event handler for anything to do with a form is to go to the designer and select the events tab in the properties window. Double clicking on the event in question generates the code needed for the event handler. In this case you need to select the form class – Form1 - and the Paint event. This generates an event handling function with the correct parameters:

private void Form1_Paint(
object sender,
  PaintEventArgs e)

The PaintEventArgs object automatically brings with it a graphics object that you can use to draw.

So to draw a line and an ellipse in a way that is permanent you would use something like:

private void Form1_Paint(
object sender,
PaintEventArgs e)
{
Graphics G = e.Graphics;
G.DrawLine(
Pens.Black,
new Point(10, 10),
new Point(100, 100));
G.DrawEllipse(
Pens.Black,
new Rectangle(10, 20, 100, 200));
}

A simpler persistent graphics

The use of the Paint event to make graphics persistent is the “standard textbook” way of doing things – but it’s not the best.

In many cases you simply want to draw at any time it suits you and have the result preserved when the form is hidden and then redisplayed. It isn’t always easy to put all your drawing commands in the Paint event handler.

The usual solution is to use a bitmap for all drawing and then use the Paint event handler to transfer, or BitBlt, the bitmap to the form.

This is workable and a useful technique but in practice there is an even easier way. Every Form has a BackgroundImage property which can be set to a background image that is automatically displayed every time the form is repainted. This is simpler but you still have to be careful to make it work properly.

First you have to create a bitmap object of the correct size:

Bitmap BImage=new Bitmap(
this.ClientSize.Width,
this.ClientSize.Height)


The result is that we now have a bitmap object the same size as the client area of the form.

Next we need to make this new, empty, bitmap the background image for the form:

this.BackgroundImage = BImage;

Following this the bitmap is displayed as the form’s background.

To draw on it all we need is a Graphics object associated with it. This is constructed using the static Graphics object:

Graphics GBack = Graphics.FromImage(
BImage);

Now that we have a Graphic object we can use all of its drawing commands as before and leave the Form object to render the bitmap each time it repaints. For example:

GBack.DrawEllipse(Pens.Black, 
new Rectangle(0, 0, 100, 200));

The good news is that now anything you draw to the GBack graphics object is persistent.

You can also create the object that you are using “on the fly” and make everything look simpler but more difficult to follow:

this.BackgroundImage = new Bitmap(
this.ClientSize.Width,
this.ClientSize.Height);
Graphics.FromImage(
this.BackgroundImage).DrawEllipse(
Pens.Black,
new Rectangle(0, 0, 100, 200));

Notice that you only have to set the form’s BackgroundImage property to an Image object once. After this you can get a Graphics object as often as you like and use it to draw on the form.

<ASIN:0735623945>

<ASIN:9812791035>

<ASIN:0130869856>



Last Updated ( Wednesday, 26 August 2009 )