Now that we’ve covered the auxiliary drawing objects, we can look at the drawing methods of the Graphics class. Before getting into the details of the drawing methods, however, let’s write a simple application that draws a couple of simple shapes on a form. First, we must create a Graphics object with the following statements:
Dim G As Graphics
G = Me.CreateGraphics
Code language: PHP (php)
Everything you’ll draw on the surface represented by the G object will appear on the form. Then, we must create a Pen object to draw with. The following statement creates a Pen object that’s 1 pixel wide and draws in blue:
Dim P As New Pen(Color.Blue)
Code language: PHP (php)
We created the two basic objects for drawing: the drawing surface and the drawing instrument. Now we can draw shapes by calling the Graphics object’s drawing methods. The following statement will print a rectangle with its top-left corner near the top-left corner of the form (at a point that’s 10 pixels to the right and 10 pixels down from the form’s corner) and is 200 pixels wide and 150 pixels tall. These are the values you must pass to the DrawRectangle method as arguments, along with the Pen object that will be used to render the rectangle:
G.DrawRectangle(P, 10, 10, 200, 150)
Code language: CSS (css)
Let’s add the two diagonals of the rectangle with the following statements:
G.DrawLine(P, 10, 10, 210, 160)
G.DrawLine(P, 210, 10, 10, 160)
Code language: CSS (css)
We wrote all the statements to create a shape on the form, but where do we insert them? Let’s try a button. Start a new project, place a button on it, and then insert the statements of Listing 14.1 in the button’s Click event handler.
Listing 14.1: Drawing Simple Shapes
Private Sub bttnDrawGraphics_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles bttnDrawGraphics.Click
Dim G As Graphics
G = Me.CreateGraphics
Dim P As New Pen(Color.Blue)
G.DrawRectangle(P, 10, 10, 200, 150)
G.DrawLine(P, 10, 10, 210, 160)
G.DrawLine(P, 210, 10, 10, 160)
End Sub
Code language: PHP (php)
Persistent Drawing
If you switch to the Visual Studio IDE or any other window, and then return to the form of the SimpleShapes application (download here), you’ll see that the drawing has disappeared! The same will happen if you minimize the window and then restore it to its normal size. Everything you draw on the Graphics object is temporary. It doesn’t become part of the Graphics object and is visible only while the control, or the form, need not be redrawn. As soon as the form is redrawn, the shapes disappear.
So, how do we make the output of the various drawing methods permanent on the form? Microsoft suggests placing all the graphics statements in the Paint event handler, which is triggered automatically when the form is redrawn. The Paint event handler passes the e argument, which (among other properties) exposes the form’s Graphics object. You can create a Graphics object in the Paint event handler and then draw on this object.
Listing 14.2 is the Paint event handler that creates the shape shown in Figure 14.6 and refreshes the form every time it’s totally or partially covered by another form. Delete the code in the button’s Click event handler and insert the statements of Listing 14.2 into the Paint event’s handler, as shown here. (Notice that the Graphics object is a property of the PaintEventArgs argument of the event handler.)
Listing 14.2: Drawing Simple Shapes in the Paint Event
Private Sub frmGraphics_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) _
Handles Me.Paint
Dim G As Graphics
G = Me.CreateGraphics
Dim P As New Pen(Color.Blue)
G.DrawRectangle(P, 10, 10, 200, 150)
G.DrawLine(P, 10, 10, 210, 160)
G.DrawLine(P, 210, 10, 10, 160)
End Sub
Code language: PHP (php)
If you run the application now, it works like a charm. The shapes appear to be permanent, even though they’re redrawn every time you switch to the form. This technique is fine for a few graphics elements you want to place on the form to enhance its appearance. But many applications draw something on the form in response to user actions, such as the click of a button or a menu command. Using the Form’s Paint event in a similar application is out of the question. The drawing isn’t always the same, and you must figure out from within your code which shapes you have to redraw at any given time. The solution is to make the drawing permanent on the Graphics object, so it won’t have to be redrawn every time the form is hidden or resized.
Forcing Refreshes
A caveat of drawing from within the Paint event is that it isn’t fired when the form is resized by default. To force a refresh when the form is resized, you must insert the following statement in the form’s Load event handler:
Me.SetStyle(ControlStyles.ResizeRedraw, True)
Code language: CSS (css)
It is possible to make the graphics permanent by drawing not on the Graphics object, but directly on the control’s (or the form’s) bitmap. The Bitmap object contains the pixels that make up the image and is very similar to the Image object. As you will see in the following chapter, you can create a Bitmap object and assign it to an Image object. To create this ‘‘permanent” drawing surface, you must first create a Bitmap object that has the same dimensions as the form (or PictureBox control) on which you want to draw:
Dim bmp As Bitmap
bmp = New Bitmap(Me.Width, Me.Height)
Code language: PHP (php)
The bmp variable represents an empty bitmap. Set the control’s Image property to this bitmap by using the following statement:
Me.BackGroundImage = bmp
Immediately after that, you must set the bitmap to the control’s background color via the Clear method:
G.Clear(Me.BackColor)
Code language: CSS (css)
If you’re using the PictureBox control to draw on, replace the BackgroundImage property with the Image property. After the execution of this statement, anything we draw on the bmp bitmap is shown on the surface of the PictureBox control and is permanent. All we need is a Graphics object that represents the bitmap, so that we can draw on the control. The following statement creates a Graphics object based on the bmp variable:
Dim G As Graphics
G = Graphics.FromImage(bmp)
Code language: PHP (php)
Now, we’re in business. We can call the G object’s drawing methods to draw and create permanent graphics on the form. You can put all the statements presented so far in a function that returns a Graphics object (Listing 14.3) and use it in your applications.
Listing 14.3: Retrieving a Graphics Object from a Form’s Bitmap
Function GetGraphicsObject(ByVal PBox As PictureBox) As Graphics
Dim bmp As Bitmap
bmp = New Bitmap(Me.Width, Me.Height)
Dim G As Graphics
Me.BackgroundImage = bmp
G = Graphics.FromImage(bmp)
Return G
End Function
Code language: PHP (php)
To create permanent drawings on the surface of the form, you must call the GetGraphicsObject() function to obtain a Graphics object from the form’s bitmap. Listing 14.4 is the revised GetGraphicsObject() function for the PictureBox control.
Listing 14.4: Retrieving a Graphics Object from a PictureBox Control’s Bitmap
Function GetGraphicsObject() As Graphics
Dim bmp As Bitmap
bmp = New Bitmap(PBox.Width, PBox.Height)
PBox.Image = bmp
Dim G As Graphics
G = Graphics.FromImage(bmp)
Return G
End Function
Code language: PHP (php)
Now that you know how to draw on the Graphics object and you’re familiar with the basic drawing objects, we can discuss the drawing methods in detail. In the following sections, I use the CreateGraphics method to retrieve the drawing surface of a PictureBox or form to keep the examples short. You can modify any of the projects to draw on the Graphics object derived from a bitmap. All you have to do is replace the statements that create the G variable with a call to the CreateGraphics() function.