Page 2 of 4
The GDI+ is object oriented and its most important object is the Graphics class.
This represents a drawing surface and provides all of the drawing methods and properties. Of course a graphics class has to be associated with a real physical graphics device or a portion of it and this is achieved when the object is first created.
Other objects that you can draw on generally already have a graphics object associated with them that you can use. This makes things seem a little more complicated at first but it soon all makes sense. For example, a common requirement is to draw on a form and to do this you simply have to access the form’s graphics object.
Start a new Windows form based application and place a button on the Form. To show how the graphics object works we are going to create an additional form to draw on in order to clarify a number of points.
In the click event handler of the button enter the following:
Form Form2 = new Form();
Form2.Visible = true;
The first line creates a new form object, Form2, from the Form class. Then it is made visible and activated, i.e. given the focus as the topmost window. Next we need to create a graphics object that is “connected” to the form’s drawing surface:
Graphics G = Form2.CreateGraphics();
To make this work add the following line to the other “using” statements:
Once you have a graphics object you can use it to draw using a collection of other objects and methods that will quickly seem obvious and intuitive. For example, there are pen and brush objects, which set the outline and fill properties for the graphics object. Many of the drawing methods accept a pen or brush as parameters. For example, the DrawLine method is:
DrawLine(Pen, Point, Point);
where Pen is an instance of a Pen object and Point is a point object. If you want to draw a red line between two points you would use:
Pen p = new Pen(Color.Red);
Point start = new Point(10, 10);
Point end = new Point(100, 100);
G.DrawLine(p, start, end);
Creating all these objects that you don’t want after you have used them once is a bit of a nuisance. The easy alternative is to create them dynamically as needed but this would result in very long and complicated method calls.
For example, the previous example can be written:
new Point(10, 10),
new Point(100, 100));
This does the same job but without having to invent names for variables and the objects are disposed of as soon as the method completes.
Once you have seen this basic construction you can start looking at the documentation for graphics objects and properties that you can use. For example as well as colour a pen can have a width:
p.Width = 5;
There is also a collection of predefined pen objects to save you the trouble of creating one. For example, to specify a standard black pen just use:
There is also a SystemPens class that will return a Pen object for the style being used to draw particular Windows components.
For example, SystemPens.Control gives a pen used to draw the outline colour of a button or control and so on.
What about shapes other than straight lines? There are additional graphics object methods for both solid and outline shapes:
You also need to know about Clear, which clears the drawing area to a specified colour, and FillRegion, which fills the interior of a region.
All these commands seem fairly obvious and well documented but you need to know that they exist to go looking for them.
You may also encounter some additional geometric objects used to define the location and size of some of the shapes. For example, a bounding rectangle object is used to specify the ellipse you want to draw. The rectangle can be specified in a number of ways but the simplest is the location of its top left-hand corner plus its height and width. For example:
Class, object and this
If you are an old hand at using objects and they way that the designer works then skip this section.
If you try to generalise the examples given above to the form that hosts the button, i.e. Form1, you will encounter a problem that is easy to solve but often puzzles beginners. You might think that Form1 is just like Form2 in the example above, and so you can write:
Graphics G = Form1.CreateGraphics();
The reason is that Form1 is a class that you are defining within your application. It inherits from the framework Form class everything it needs to be a form and you then add additional methods and properties. This is what the designer does when you add buttons and other controls. In short you customise a form by creating a new class that inherits from Form. Then the generated code creates a single anonymous instance of that class which is the form object you see and interact with.
The code that creates the form object from the class is generated automatically by the designer. If you look inside the program code you will find the last line is:
This creates the new Form1 object, i.e. an instance of the Form1 class, as a new thread of execution but without giving the new object a name.
So how do you refer to the object and get its associated graphics object?
The answer is the keyword “this”. Within a class “this” means “the current object instance created using the class. So instead of:
Graphics G = Form1.CreateGraphics();
you have to use
Graphics G = this.CreateGraphics();
within the Form1 class if you want to draw on objects created from the Form1 class.