This article
has been excerpted from book "GraphicsProgramming with GDI+".
One of the best programming practices is the efficient use of variable and their
scope. Before adding a new variable to a program, think for a second and ask
yourself, "Do I really need this variable?" If you need a variable, do you
really need it right now? The scope of variables and use of complex calculations
can easily degrade the performance of your applications. Using global scope for
pens, brushes, paths, and other objects may be useful instead of defining
variable in the OnPaint or OnPaintBackGround methods.
Let's look at a practical example: Listing 13.5 is written on a form's paint
event handler, which creates pens and brushes, and draws rectangles and
polygons.
LISTING 13.5: Variables defined in the form's paint event handler
using
System;
using
System.Collections.Generic;
using
System.ComponentModel;
using
System.Data;
using
System.Drawing;
using
System.Drawing.Design;
using
System.Drawing.Text;
using
System.Linq;
using
System.Text;
using
System.Windows.Forms;
using
System.Drawing.Drawing2D;
namespace
ScopeType
{
public partial
class Form1 :
Form
{
public Form1()
{
InitializeComponent();
}
private void
Form1_Paint(object sender,
PaintEventArgs e)
{
//Create
brushed and pens
HatchBrush hatchBrush =
new HatchBrush(HatchStyle.HorizontalBrick,
Color.Red, Color.Blue);
Pen redPen =
new Pen(Color.Red,
2);
Pen hatchPen =
new Pen(hatchBrush,
4);
SolidBrush brush =
new SolidBrush(Color.Green);
//Create a points for curve
Point p1 =
new Point(40,
50);
Point p2 =
new Point(60,
70);
Point p3 =
new Point(80,
34);
Point p4 =
new Point(120,
180);
Point p5 =
new Point(200,
150);
PointF[] ptsArray = { p1, p2, p3,
p4, p5 };
float width =
this.ClientRectangle.Width - 100;
float height =
this.ClientRectangle.Height - 100;
//float width = this.ClientRectangle.Width
– 100;
//float height =
this.ClientRectangle.Height – 100;
Point pt1 = new
Point(40, 30);
Point pt2 =
new Point(80,
100);
Color[] lnColors = {
Color.Black,
Color.Red };
LinearGradientBrush lgBrush =
new
LinearGradientBrush(pt1, pt2, Color.Red,
Color.Green);
lgBrush.LinearColors = lnColors;
lgBrush.GammaCorrection = true;
//Draw objects
e.Graphics.DrawPolygon(redPen, ptsArray);
e.Graphics.DrawRectangle(hatchPen, x, y, width, height);
e.Graphics.FillRectangle(lgBrush,
200, 200, 200, 200);
//Dispose of objects
lgBrush.Dispose();
brush.Dispose();
hatchPen.Dispose();
redPen.Dispose();
hatchBrush.Dispose();
}
}
}
In this example we define many variables, all of local scope. Throughout the
application, the redPen, hatchBrush, hatchPen, brush, and other variable remain
the same. Programmatically, it doesn't matter whether we define these variables
locally or globally; the choice depends entirely on the application. It may be
better to have variables defined with a global scope. If you repaint the form
frequently, defining these variables globally may improve performance because
time will not be wasted on re-creating the objects for each pass. On the other
hand, defining objects globally may consume more resources (memory).
It is also good to avoid lengthy calculations in frequently called routines.
Here's an example: Listing 13.6 draws a line in a loop. As you can see, int x
and int y are defined inside the loop.
LISTING 13.6: Defining variable inside a loop
for (int i = 0;
i < 10000; i++)
{
Pen bluePen =
new Pen(Color.Blue);
int x = 100;
int y = 100;
g.DrawLine(bluePen, 0, 0, x, y);
}
We can easily replace the code in Listing 13.6 with Listing 13.7, which is more
efficient. If a code statement does the same thing every time a control reaches
it inside a loop, it is a good idea to move that statement outside the loop to
save processing cycles.
LISTING 13.7: Defining variable outside a loop
Pen bluePen = new
Pen(Color.Blue);
int x = 100;
int y = 100;
for (int
i = 0; i < 10000; i++)
{
g.DrawLine(bluePen, 0, 0, x, y);
}
Sometimes using a floating point data type instead of an integer may affect the
quality of a drawing, even though floating point data is costly in terms of
resources.
A well-designed and well-coded application also plays a vital role in
performance. For example, replacing multiple if statements with a single case
statement may improve performance.