This article
has been excerpted from book "GraphicsProgramming with GDI+".
Drawing on the Web works differently from drawing in the Windows Forms. On the
Web we have many limitations, one of which is no pixelwise drawing support in
the Web browser. Our approach was to convert our graphics objects into a
temporary bitmap image and view the image in a Web browser.
Double buffering is a similar concept. You may have seen one of the frequently
asked questions on GDI+ discussion forums: "How do we create flicker-free
drawings"? The double buffering technique is used to provide faster, smoother
drawings by reducing flicker. In this technique, all objects are drawn on an
off-screen canvas with the help of a temporary image and a Graphics object. The
image is then copies to the control. If the drawing operation is small and
includes drawing only simple objects such as rectangle or lines, there is no
need for double buffering (it may even degrade performance). If there are many
calculations or drawn elements, performance and appearance may be greatly
improved through the use of double buffering.
To provide the point, let's write an example. Listing 13.8 gives the code for a
drawing method that draws several lines.
LISTING 13.8: The DrawLine method
private void
DrawLine (Graphics g)
{
float
width = ClientRectangle.Width;
float
height = ClientRectangle.Height;
float
partX = width / 1000;
float
partY = height / 1000;
for
(int i =0; i<10000; i++)
{
g.DrawLine (Pens.Blue,
0, height - (partY * i),
partX * i, 0);
g.DrawLine (Pens.Green,
o,
height - (partY * i),
(width) - partX * i, 0);
g.DrawLine (Pens.Red, 0,
partY * i,
(width) - partX * i, o);
}
}
To test our application, we will call it from a button click. The code for a
button click event handler is given in Listing 13.9.
LISTING 13.9: Calling the DrawLines method
//Create a Graphics object for "this"
Graphics g =
this.CreateGraphics();
g.Clear(this.BackColor);
//Draw lines
DrawLines(g);
//Dispose of object
g.Dispose();
Figure 13.4 shows the output from Listing 13.9.
Now let's draw the same lines using a Bitmap object. We create a temporary
Graphics object from a temporary image and call its draw and fill methods.
Instead of calling DrawLine with respect to a form, we call DrawImage, which
draws the image generated by the DrawLine method.
FIGURE 13.4: Drawing lines in a loop
As Listing 13.10 shows, we create a Bitmap object in a buffer and send the
entire buffer all at once using DrawImage. We add the code given in Listing
13.10 on the Bitmap Draw button click event handler.
LISTING 13.10: Using double buffering to draw
Graphics g = this.CreateGraphics();
g.Clear(this.BackColor);
//Create a Bitmap object with the size of
the form
Bitmap curBitmap =
new Bitmap(ClientRectangle.Width,
ClientRectangle.Height);
//Create a temporary Graphics object from
the bitmap
Graphics g1 =
Graphics.FromImage(curBitmap);
//Draw lines on the temporary Graphics
object
DrawLines(g1);
//Call DrawImage of Graphics and draw
bitmap
g.DrawImage(curBitmap, 0, 0);
//Dispose of objects
g1.Dispose();
curBitmap.Dispose();
g.Dispose();
Comparing the two methods given in Listing 13.9 and 13.10 reveals a significant
difference in drawing performance. In Listing 13.9, drawing begins as soon as we
hit the Simple Draw button and continues until it is done. By contrast, when we
hit the Bitmap Draw button, drawing doesn't start immediately. This method
actually draws on an in-memory Bitmap object, and when all drawing is done, it
displays the bitmap.