Beginning Visual Basic (Visual Studio 2008) - Project 9

Menus, Timers, and Drawing Shapes

Project 9

Close your last project and creating a new one

If you still have the Project8 project open, select the Close Project item on the file menu to close it.

With no open projects, click on the Project... option next to Create: on the Start Page, or pick New Project item on the File drop-down menu. 

The Add New Project dialog appears.  With the Windows Application template selected, type Project9 for the name and click the OK button.  Now click the Save All button on the toolbar to save the project.  Be sure to uncheck the Create directory for solution option on the Save Project dialog box.  Do not change the default Location path and click the Save button. 

This creates a new folder inside the My Documents\Visual Studio 2008\Projects\  folder named Project9:

        My Documents\Visual Studio 2008\Projects\Project9

Rename the Form file and the Form and set the BackColor property to White

With the form file (Form1.vb) selected in the Solution Explorer window, the Properties window directly below it displays it's File properties.  Click on the File Name property and type frmProj9.vb (don't forget to include the .vb extension).  To display the properties of the form in the Properties window, click once on the blank Form, which should be displayed on the left side of the screen in the Design window.  Make sure the Name property—which is in parentheses (Name) at the top of the property list so that it's easy to find—is frmProj9.  Then scroll the properties windows down and change the Text property to Project 9.

Before going on, click on the Save All button on the toolbar to save your project.
 


Creating a Menu

For your ninth Visual Basic project, you will create a program where the only Controls are a Timer and a MenuStrip with the following structure (suggested Names are italicized in parentheses following the Text names):

Menu Table
Level 1
Text
Level 2
Text
Level 3
Text
Name Checked
&File     (default name)  
  &Shape   (default name)  
    &Square mnuSquares True
    &Rectangle mnuRectangles False
    &Circle mnuCircles False
    &Ellipse mnuEllipses False
  &Clear   mnuClear False
  &Go   mnuGoStop False
  (Insert Separator)      
  E&xit   mnuExit False

The Menu Table above builds this menu:

Adding a MenuStrip control to the form

Double-click on the MenuStrip item in the Menus & Toolbars section of the Control Toolbox to add a MenuStrip control (MenuStrip1) to the Component Tray.  Once added to your project, the MenuStrip control appears in the Component Tray at the bottom of the design window, like this:

To add the MenuStrip1 to the form, set the MainMenuStrip property of the form to MenuStrip1, like this:

After setting the MainMenuStrip property to MenuStrip1 (which may have been set automatically when you added it to the component tray) click once on the MenuStrip1 control in the Component Tray to selected it.  Once MenuStrip1 is selected in the Component Tray, the new blank menu should appear in the upper left corner of the form, like this illustration from Project 8:

Use the Menu Table above to guide you, and complete the rest of the menu. 

Adding a Timer control to the form

When the user selects a Shape (Squares will be the default. Did you set the Checked property of the mnuSquares menu item to True?), they then choose the Go menu item. This will enable the Timer control. The Go menu item’s Text changes to Stop once the Timer has started. The shape the user selected will be drawn on the Form at random places, in random sizes, and with random colors. Each tick of the Timer will draw another shape, until the user selects Stop from the Menu. When the user selects Stop, the Timer is disabled, and the Stop menu item’s Text changes back to Go. Choosing the Clear menu item erases any shapes on the form.

Add the Timer control to the Component Tray by double clicking on the Timer control icon in the Control Toolbox.  It is located at the bottom of the Components section, as shown: 

The Timer control appears as a small stop watch icon in the Component Tray, like this:

Set these properties of the Timer control:

Timer
Property Value
Name tmrDraw
Enabled False
Interval 200

A Timer control has only 1 event procedure—Tick. The code that you place in the tmrDraw_Tick event procedure is executed every time the Tick event procedure happens. The number of ticks per second is set with the Interval property which uses milliseconds (milliseconds is thousandths of a second). So setting the Interval property to 200 milliseconds raises the Tick event every 2/10’s of a second, and setting the Interval property to 1000 milliseconds raises the Tick event once a second.

Add the following code to the Declarations section:

'Create a constant with a unique value for
'    each shape.
Const SQUARE As Integer = 1
Const CIR As Integer = 2
Const RECT As Integer = 3
Const ELLIPSE As Integer = 4
'iDrawWhat will be set to the shape the user
'    selects.  SQUARE is the default shape.
Dim iDrawWhat As Integer = SQUARE

The code for the mnuGoStop event procedure

Here is the code that goes into the mnuGoStop_Click event procedure:

'Does the mnuGoStop menu item say Go?
If mnuGoStop.Text = "&Go" Then
     'Change the mnuGoStop menu
     '    item to Stop.
    mnuGoStop.Text = "&Stop"
     'Turn on the tmrDraw timer
    tmrDraw.Start()
Else
     'Change the mnuGoStop menu
     '    back to Go.
    mnuGoStop.Text = "&Go"
     'Turn off the tmrDraw timer
    tmrDraw.Stop()
End If

Notice how a Menu’s Text property value can be examined and changed dynamically. The Timer is also turned on and off within this procedure by using its Start and Stop methods.

The code for the tmrDraw_Tick event procedure

Here is the code from the tmrDraw_Tick event procedure that generates the random number values needed to draw the shapes with random colors (iColor), at random sizes (iSize), and at random places on the screen (iX, iY):

'Values for all these variables will be
'    randomly generated.

Dim iRed, iGreen, iBlue As Integer
Dim
iX, iY As Integer
Dim
iSize As Integer
'Determines the width of rectangles
'    and ellipses.

Dim iRectWidth As Integer   

'Create a Graphics class reference variable
Dim g As Graphics   
'Refer g to the Graphics object of the form
'    (Me).  This will allow us to use the
'    DrawRectangle and DrawEllipse methods.
g = Me.CreateGraphics

'Seed the random-number generator. We really
'    only need to do this once, so you could
'    move this line of code to the frmProj9_Load.

Randomize()   

'Generate a random values between 0 and 255
'    for the color luminosity values--remember
'    Project 2.
iRed = Int(Rnd() * 256)
iGreen = Int(Rnd() * 256)
iBlue = Int(Rnd() * 256)
'Create a drawing Pen, specifying it's color
'    and thickness.
Dim DrawPen As New 
_
   
Pen(Color.FromArgb(iRed, iGreen, iBlue), 1)

'Generate a random value between 5 and 50,
'    for the size of the shapes in pixels.
iSize = Int(Rnd() * 46) + 5
'Generate X and Y starting points for drawing
'    the shape within the form area.
iX = Int(Rnd() * Me.Width) + 1
iY = Int(Rnd() * Me.Height) + 1    

Get Visual Basic Help on the Randomize command, and the Rnd function to find out what they do and how they work (a brief explanation of Rnd follows):

The Rnd function returns a random number between 0 and .99999.  Let’s say you want a random number between 1 and 15. This is how the code to do that would look (don't type this code example into your program!):

Int(Rnd() * 15) + 1

Here is the above line broken down into 3 basic parts:

'Generates a number between 0 and
'    14.99999, because (15 * 0) = 0,
'    and (15 * .99999) = 14.99999
Rnd() * 15

'Makes the number between 1 and
'    15.99999, because (15 * 0) + 1 = 1,
'    and (15 * .99999) + 1 = 15.99999
Rnd() * 15 + 1

'Uses the Int function to remove the
'    decimal value so number is 1 to 15.
Int(Rnd() * 15) + 1

Drawing shapes with the Graphics object of the form

We created a g Graphics object reference variable in the first part of the code from the tmrDraw_Tick event procedure above so that we could set a reference to the Graphics class of the form like this:

'Create a Graphics class reference variable
Dim g As Graphics   
'Refer g to the Graphics object of the form
'    (Me).  This will allow us to use the
'    DrawRectangle and DrawEllipse methods.
g = Me.CreateGraphics

This gives us the ability to draw on the form with the many drawing methods that are part of the form's Graphics class.  A small list of some of these methods include:

  1. DrawRectangle - Draw rectangles and square
  2. DrawEllipse - Draw ellipses and circles
  3. DrawPolygon - Draw multi-sided shapes
  4. DrawArc - Draw arcs of different lengths
  5. DrawBezier - Draw Bezier curves

There are many more:

Here is the rest of the code for the tmrDraw_Tick event procedure (place this below the code you added to the tmrDraw_Tick event procedure already). We will use a Select Case statement to determine which shape to draw depending upon the value of iDrawWhat—which is an Integer that we dimensioned in the Declarations section—get help on the Select Case structure):

'Since iDrawWhat can be one of 4 different
'    values, a Select Case structure is better
'    suited to test it than If-Then-Else--which is
'    best for testing for only 2 different values.
Select Case iDrawWhat
    Case
SQUARE 
'If iDrawWhat is equal to SQUARE do this
       
g.DrawRectangle(DrawPen, iX, iY, iSize, iSize)
    Case
CIR         
'If iDrawWhat is equal to CIR do this
       
g.DrawEllipse(DrawPen, iX, iY, iSize, iSize)
    Case
RECT
            'If iDrawWhat is equal to RECT do this
         
iRectWidth = iSize / 2
       
g.DrawRectangle(DrawPen, iX, iY, iRectWidth, iSize)
    Case
ELLIPSE  
'If iDrawWhat is equal to ELLIPSE do this
          iRectWidth = iSize / 3
       
g.DrawEllipse(DrawPen, iX, iY, iRectWidth, iSize)
End Select

Most of the drawing methods take a Pen as their first parameter.  The code we used to create a Pen (DrawPen) in the tmrDraw_Tick event procedure looked like this:

'Create a drawing Pen, specifying it's color
'    and thickness.
Dim DrawPen As New  _
   
Pen(Color.FromArgb(iRed, iGreen, iBlue), 1)

The Pen determines the color and thickness (in pixels) that the lines will be drawn in:

        g.DrawRectangle(DrawPen, iX, iY, iSize, iSize)

The second and third parameters passed to the drawing methods specify the X, Y location on the form where the upper left corner of the shape will be drawn:

        g.DrawRectangle(DrawPen, iX, iY, iSize, iSize)

The last two parameters specify the width and height of the shape:

        g.DrawRectangle(DrawPen, iX, iY, iSize, iSize)

Because most of the drawing methods are Overloaded, the parameters you pass to them can be formatted several different ways.  For example, the DrawRectangle method can be called with just two parameters, a Pen and a Rectangle, like this (do not type this code):

Dim MyRect As New Rectangle()
MyRect.X = iX
MyRect.Y = iY
MyRect.Width = iSize
MyRect.Height = iSize
g.DrawRectangle(DrawPen, MyRect)

In the code above we pass a Rectangle class variable as the single second parameter to the DrawRectangle method call.  That Rectangle (MyRect) includes all the information that 4 single parameters provided for the original way we call the DrawRectangle method. 

Method Overloading, multiple parameter format options

The above code is just one example of an alternate way of calling the DrawRectangle method (you don't need to change your code).  Method Overloading is very common in Visual Studio.  Look at the following illustration that shows the smart tag for the DrawRectangle method.  Notice the circled up/down arrow buttons.  You can select up to 3 different parameter formats for this method.  Number 1 is the example I just showed above—Where only 2 parameters, a Pen and Rectangle, are required.  You can click on those little arrow buttons to see a description of the different parameter format options:

You will notice that many, if not most, method calls support a variety of parameter formats.  Which format you use is up to you.  Why did Microsoft design methods this way?  Because depending upon the situation, one format would be better suited than another.  And having the option to choose the best format makes a big difference in code readability, so that long term maintenance of code is easier and less error prone.  It's actually very easy to create your own Overloaded methods for custom classes that you create—More on that in the advanced VB class.

Using the menu to pick Shapes

Not too much information here.  Just the code from the mnuSquares_Click event procedure:

If mnuSquares.Checked <> True Then
      mnuSquares.
Checked = True
      mnuCircles.
Checked = False
      mnuRectangles.
Checked = False
      mnuEllipses.
Checked = False
      
iDrawWhat = SQUARE
End If

The code for the Click event procedures of the other shape menu items is very similar to the above code.

Testing the program

Test your program thoroughly.

Required Enhancements

          Hint: Here’s some code that makes a simple 3D pyramid by drawing five separate lines:

x1 = iX
y1 = iY
x2 = iX + iSize / 2
y2 = iY + iSize
g.
DrawLine(DrawPen, x1, y1, x2, y2)
x1 = iX
y1 = iY
x2 = iX - iSize / 2
y2 = iY + iSize
g.
DrawLine(DrawPen, x1, y1, x2, y2)
x1 = x2
y1 = y2
x2 = iX + iSize / 2
y2 = iY + iSize
g.
DrawLine(DrawPen, x1, y1, x2, y2)
x1 = x2
y1 = y2
x2 = iX + iSize * 0.75
y2 = iY + iSize / 2
g.
DrawLine(DrawPen, x1, y1, x2, y2)
x1 = iX
y1 = iY
x2 = iX + iSize * 0.75
y2 = iY + iSize / 2
g.
DrawLine(DrawPen, x1, y1, x2, y2)

Another Hint: Use the Visual Studio help system and get help on the DrawPolygon method, and take a look at some of the example code that uses it.


To copy a Project folder from your Projects folder on the Hard Drive to a floppy diskette or pen-drive follow these steps:

  1. Exit Visual Studio 2008 and insert the floppy diskette or pen-drive, that you want to copy the Project9 folder to:
  2. Select the My Documents item on the Start Menu to open the My Documents folder.
  3. In the My Documents folder, double-click the Visual Studio 2008 folder to open it.
  4. Double-click on your Projects folder to open it.
  5. Open the Project9 folder by double-clicking on it.  Inside the Project9 folder, delete the Obj and Bin folders—these folders are created automatically when you open a project.  You do not need to copy them, or their contents, to your floppy diskette or pen-drive.  Important: Be sure not to delete the My Project folder or Resources folder, if it exists.
  6. Once you have deleted the Obj and Bin folders, hit the Backspace key once—or click the Back button on the toolbar.  This moves you from inside the Project9 folder to back inside your Projects folder.
  7. Right-click on the Project9 folder and selected: 31/2" Floppy A: or your pen-drive on the Send To fly-out menu.  This copies the Project9 folder to your floppy diskette or pen-drive.