![]() |
Languages »
VB.NET »
Windows Forms
Intermediate
Presidential MemoryBy Thomas BlumThis article describes a VB .NET project that has two Forms that do not have an MDI parent-child relationship |
VB, Windows, .NET 1.1VS.NET2003, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||


Two scenarios that were easier to code in Visual Basic Version 6 are
The game Memory, also known as Concentration, has pairs of images arranged randomly within
a rectangle. A turn consists of a player's clicking on two PictureBoxes. If they match
(i.e. have the same image), the player scores a point and continues. If the images do not
match, the images are covered again and the next player takes a turn. Covering the mismatched
images is done in code using a timer's Tick event -- a delay is required so that the player
can see the images' locations and that they do not match. This version of the game
also allows for a single player who plays against the clock.
This version of the game consists of two Windows Forms.
Form (see the first screen capture above). It has two Panels.
The upper Panel allows the player to select the size of the board by selecting the number of
rows and columns using NumericUpDown controls. The lower Panel allows for various players'
names to be added to a ListBox. The names can be removed as well as promoted or demoted
within the list to alter the order of players. Below the Panels is the Play Button which moves
one to the next Form.
Panel will hold a dynamic array of UserControls that will display the players' names
and scores. The lower panel will hold a dynamic array of PictureBoxes that serve as the basic
elements of the Memory game. Below the Panels are two Buttons. The first of these allows one
to return to the setup form, and the second allows one to start a new game.
In order to move back and forth between two Forms, the specific names of the both Form
objects (as opposed to just the names of the Form classes) must be known to the programmer.
This can be achieved by explicitly instantiating both Form objects (with
Public access) in
the Sub Main of a code module and choosing the code module as the
project's Startup object. Sub Main then calls the setup Form's
ShowDialog method. The code module is shown below:
Module modStart
'declare and instantiate an object of each of the form classes
Public FrmBoard As New FrmPresidentialMemory
Public FrmSetup As New FrmGameSetup
'the program starts here and moves on to display the setup form object
Public Sub Main()
FrmSetup.ShowDialog()
End Sub
End Module
It is important here to use the ShowDialog method and not the Show
method since the ShowDialog method is modal and hence does not allow the
Sub Main to complete execution until the Form in question is closed. With
the modeless Show method, the Form appears briefly on the screen but is
closed when Sub Main completes execution.
To move from the first Form (setup) to the second Form (board), one uses the combination
Me.Hide()
FrmBoard.ShowDialog()
again using the ShowDialog method. However, to move from the second Form
(board) to the first Form (setup), one uses
Me.Hide()
FrmSetup.Show()
As the setup Form was previously hidden and not closed, use of the ShowDialog
method here would cause an error. The Forms are not displayed in independent threads, closing either
Form returns one to Sub Main and terminates the project.
Another question that arose was which Form Event should be used to load the dynamic
control arrays. (Recall that the dynamic control arrays may be repeatedly loaded as the user can
change the number of players or size of the game board.) The Help for the Load
event states that it "occurs before a form is displayed for the first time"
(author's emphasis). However, placing a MessageBox in the Load event code
showed that it executed more than once as the user moved between the two forms despite the fact that
the forms were hidden and not closed. (Changes made by the user to the setup Form persist
implying that the Form remains in memory.) Because the description of Load in
Help and its behavior in this program appeared to be inconsistent, using it was avoided. The
code that only needed to be executed once (the reading of the file with the image file names)
was moved to the constructor (Sub New) in the Windows Form
Designer generated code after InitializeComponent(). On the other hand,
the code that was to be executed each time the user moved from the setup form to the board form was
placed in the VisibleChanged method as shown below.
Private Sub FrmPresidentialMemory_VisibleChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.VisibleChanged
If Me.Visible Then
SetUpBoard()
End If
End Sub
Since the VisibleChanged event is raised when the form is hidden and when
it is shown, the If statement above limits the setup code execution to when
the form is shown. Events such as Activated and GotFocus
can be raised more often than desired for present purposes -- for instance, if the user is interacting
with other applications on the desktop.
Setting up the board requires generating a dynamic array of picture boxes which consists of
'remove game elements of any previous board setup
panBoard.Controls.Clear()
'instantiate array of pictureboxes for game elements
GameElement = New PictureBox(nRowNumber * nColumnNumber - 1) {}
'instantiate and position individual game elements (pictureboxes)
'creates rows of game elements with nColumnNumber elements in each row
'and assigns them an eventhandler
For i = 0 To GameElement.GetUpperBound(0)
GameElement(i) = New PictureBox
panBoard.Controls.Add(GameElement(i))
GameElement(i).Size = New System.Drawing.Size( _
ELEMENT_WIDTH, ELEMENT_HEIGHT)
GameElement(i).Location = New System.Drawing.Point( _
GameElement(0).Width * (i Mod nColumnNumber), _
GameElement(0).Height * (i \ nColumnNumber))
GameElement(i).SizeMode = PictureBoxSizeMode.StretchImage
AddHandler GameElement(i).Click, AddressOf GameElementHandler
Next
In VB Version 6 the method handling the event of a dynamic array included an Index as
part of its signature. In VB .NET the handler has the same signature as the method for a
single control. The index is then determined by performing a search as shown in the code below.
nFirstElementIndex = Array.IndexOf(GameElement, sender)
Strictly speaking one does not need an array of PictureBoxes, one could simply add individual controls to the panel as done in the article on Control Arrays by ManoRajan (http://www.codeproject.com/vb/net/Control_Arrays.asp) and use the panel's collection of controls. But there are at least two conveniences provided by having a genuine array.
UserControl
was introduced.
The main purpose of the UserControl
was the association of the Label and the TextBox, which
requires no code beyond the Designer generated code. However, the PlayerName
property was introduced so that one did not have to access the Text property of the Label within
the UserControl, but instead needed only the UserControl's PlayerName
property (e.g.
MyScore(i).PlayerName replaces
MyScore(i).lblName.Text). Similarly a Score Property and
Increment subroutine were added. Furthermore, the LabelTextbox
UserControl
was designed
specifically for this project so that the default size could be used when loading them
onto the panel.
nudColumn
(a NumericUpDown
control) was set to 4 and the Increment property was set to 2. These settings impose
the condition without the need for any additional code.
ListBox
when the Play Button is clicked, a single
player named "Player 1" is added.
TextBox
is made visible since in this case the user is
playing against the clock. If there are multiple players, then this TextBox
is made invisible.
'Move to next player and underline his or her name
MyScore(nPlayerIndex).lblName.Font = New Font( _
New FontFamily(MyScore(0).lblName.Font.Name), _
MyScore(0).lblName.Font.Size, FontStyle.Bold)
nPlayerIndex = (nPlayerIndex + 1) Mod MyScore.GetLength(0)
MyScore(nPlayerIndex).lblName.Font = New Font( _
New FontFamily(MyScore(0).lblName.Font.Name), _
MyScore(0).lblName.Font.Size, FontStyle.Underline _
Or FontStyle.Bold)
I would like acknowledge useful discussions with S. Longo and S. Wiley.
| You must Sign In to use this message board. | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 24 May 2004 Editor: Nishant Sivakumar |
Copyright 2004 by Thomas Blum Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |