Ticket Printer

28 points

 

Setting up the Form
Start a New Project.

Add the main Button (it will be Button1) to the form. This is the Button that, in the image below, says 'Calculate the Cost, Make Change and Print Ticket'. Set the Design > Enabled property of Button1 to False. This prevents the user from clicking the button until later.

Password
Add a Label, a TextBox (rename it 'txtPassword') and a Button. Change the Label's Text property to "FIRST, ENTER YOUR PASSWORD:". Change the Text property of the Button to 'Submit Password' or something else. You can see these controls in the upper-right of the image below.

Movies
Add a ComboBox (rename it 'cmbMovies') to the form.
Add movies to cmbMovies. To do this, in Design View, click on the ComboBox. Click the small 'Play' icon at the top of the ComboBox. Then choose Edit Items. Enter the movie names in the String Collection Editor. Change the Appearance > Text property to 'Movies?' or something else.
Add a Label. It can reside just below the ComboBox and display the price of seeing a movie.

Number of Tickets
Add a GroupBox to the form, and rename it 'GroupBoxTickets'. This is a rectangle that holds the 6 radio buttons for the number of tickets the customer wants to buy.
Add 6 RadioButtons to GroupBoxTickets. Modify the Appearance > Text property to 1, 2, 3, 4, 5 or 6. To make the radio buttons look good, you can select them and use Format > Align > Tops and Format > Horizontal Spacing > Make Equal.
Outside of GroupBoxTickets, add a TextBox (rename it 'txtNumTickets') and a Label. The Label can say 'Other:'. If the customer is buying more than 6 tickets, the number of tickets can be entered into txtNumTickets.

Customer Payment
Add a second GroupBox, and rename it 'GroupBoxMoney'. Add 4 radio buttons to GroupBoxMoney, and change the Text property to $100, $50, $20 and $10. (We'll assume the customer pays with cash.) Also add a Label and TextBox (rename it 'txtPayment'), in case the customer pays with more than 1 bill.
Next, add a Label (rename it 'lblChange') which will display how much change the customer is owed.
Finally, add a Label (rename it 'lblWarning') which will display a warning message like 'More Money Needed' when the customer still owes money.

Ticket
Below Button1, add a GroupBox. The GroupBox will contain the ticket that will be issued to the customer. Add a Label to the GroupBox, and rename it 'lblTicket'.


This is the form that the user sees after he enters his first and last name, but before he submits his password.

 


This is the form that the user sees after successfully submitting her password, and while using the software.

 

Writing the Code

First Lines
Go to Code View. Change the Appearance > Text property of the form. Write this as the first line, above 'Public Class Form1': Option Explicit On. This requires you to declare variables, which is a good idea.
The next line should be: Imports mvb = Microsoft.VisualBasic. This allows you to use 'mvb' as a shortcut for 'Microsoft.VisualBasic'.

Adding Global Variables
Add the following variables to the project, below 'Public Class Form1'. These variables will be available in all of the methods.
- a String 'first' (the user's first name)
- a String 'last' (the user's last name)
- a String 'initials' (the user's initials)
- a String 'movie' (the movie that the customer wants to see)
- a double 'payment' (the money that the customer pays)
- an int 'numTickets' (the number of tickets that the customer buys)
- a double 'cost' (the price of the tickets that the customer buys)

When the User Starts the Ticket Printer Software
From the left dropdown menu, under Form1, select 'Form1 (Events)'. From the right dropdown menu, select 'Load'. You can then write code in 'Private Sub Form1_Load'. Code in 'Form_Load' runs early, as the form is loading.
Use 'InputBox' to ask the user for his/her first name. This is the code: first = InputBox("What is your first name?"). Then ask for the user's last name.
Still in Form1_Load: the 'Left' function returns a desired number of characters at the start of a word. To extract the first character of the first name, the code is: mvb.Left(first, 1). Also extract the first character of the last name, and then concatenate the 2 characters (with a '&') and assign the result to 'initials'.

Password
You want the password to display as *****. Select txtPassword from the left dropdown, and KeyPress from the right dropdown. The object 'e' contains the character that was just pressed. To change this character to an asterisk, in 'Private Sub txtPassword_KeyPress' put this 1 line of code: e.KeyChar = "*".

When the button next to txtPassword is clicked, you can accept or reject the password. We keep it simple - the only check you do on the password is to check if it is 6 (or more) characters long. If so, the password is accepted. If not, the user has to enter a different password.
Inside the Click() function for this button, use the Len() function to find the length of txtPassword.Text. The code could be: length = Len(txtPassword.Text). In an IF statement, check if the password is long enough. If it is, make these 3 controls invisible by changing their Visible property to false. Also, change the Enabled property of Button1 to True, thus allowing the user to use the software. Finally, call the method resetForm() like this: Call resetForm().
If, on the other hand, the password is 5 characters or fewer, use 'MsgBox()' to pop up a box instructing the user to enter a password that is 6 or more characters long. Return the focus to txtPassword with this code: txtPassword.focus(). And clear txtPassword like this: txtPassword.Text = "".

Clear Everything for the Next Customer
You need a method that you can call that resets all the controls, making the form ready for the next customer. The first line of the new method can be: Private Sub resetForm(), and its last line can be: End Sub. In resetForm():
- set the Checked property of all of the RadioButtons to False. For example: radPayment1.Checked = False.
- Clear the controls txtNumTickets, txtPayment, lblTicket, lblWarning and lblChange. For example: txtNumTickets.Text = "".
- Set 'payment' equal to 0.

The Customer Chooses a Movie
Double-click on the ComboBox that contains the list of available movies. You'll write the code for: Private Sub cmbMovies_SelectedIndexChanged(). First call resetForm() like this: Call resetForm(). Call the selectedItem() method on the cmbMovies object, and assign the result to the String 'movie'.

Payment from a Customer
You can have a method that figures out how much money the customer is paying with. It's a bit complicated, so the complete method is listed below. You can copy the method directly into your program. You'll write a similar method to calculate how much the customer owes for his/her tickets, so let's go through this method.


Private Sub getPayment()
Dim amt As String
If txtPayment.Text <> "" Then
     payment = CDbl(txtPayment.Text)
Else
     For Each ctrl In GroupBoxMoney.Controls
          If TypeOf ctrl Is RadioButton Then
               If ctrl.checked Then
                    amt = ctrl.text
                    amt = amt.Substring(1)
                    payment = CDbl(amt)
               End If
          End If
     Next
End If
End Sub

In Visual Basic, 'not equals' is written '<>'. So the first IF statement says, 'If txtPayment is not empty, assign what is in txtPayment to the variable payment'. The command CDbl() converts the contents of txtPayment to a double.
The program enters the 'Else' if txtPayment is empty, so it is necessary to see which RadioButton is checked. The line For Each ctrl In GroupBoxMoney.Controls says 'Consider each control in GroupBoxMoney, one at a time.' Now, not every control in GroupBoxMoney is a RadioButton; there are also Labels and TextBoxes in GroupBoxMoney.
So the next line: If TypeOf ctrl Is RadioButton Then says, 'Continue only if the given control is a RadioButton'. If it is:
- assign the Text property of the RadioButton to the variable 'amt'
- remove the $ in front of the number. amt.Substring(1) says 'Extract the characters in amt, starting with the character at position 1'. Keep in mind that Strings begin at position 0, so this has the effect of removing the $ in front of the number.
- convert 'amt' to a double and assign it to the variable 'payment'
Thus, whether a number is entered into txtPayment or instead a RadioButton is checked, the correct value is assigned to 'payment'.

Price of the Tickets
You can have a method getNumTickets() that figures out how much the customer owes for his/her tickets. It can be similar to getPayment(), listed above. If txtNumTickets has a number in it, assign the number to 'numTickets'. On the other hand, if txtNumTickets is blank, step through the RadioButtons in GroupBoxTickets one at a time. (Since GroupBoxTickets contains only RadioButtons, a line like If TypeOf ctrl Is RadioButton Then is not necessary here.) If a given control (RadioButton) is checked (if its Checked property is True), assign its value to 'numTickets'. You can use the command CInt() to convert the RadioButton's Text property to an integer.

Clear Tickets RadioButtons
You can have a method clearTicketsRadioButtons() that clears the RadioButtons in GroupBoxTickets. Set up a For Each loop, like the ones above, and set the Checked property of each RadioButton in GroupBoxTickets to False.

Clear Payment RadioButtons
You can have a similar method clearPaymentRadioButtons() that clears the RadioButtons in GroupBoxMoney. As in the method getPayment(), it will be necessary to include the line If TypeOf ctrl Is RadioButton Then inside the For Each loop.

Clear Tickets RadioButtons if txtTickets is Changed
If a change is made to txtTickets, you want to clear (uncheck) the RadioButtons in GroupBoxTickets. You don't want a number to be written in txtTickets and have a RadioButton checked.
From the left dropdown menu, choose txtTickets. From the right dropdown menu, choose Text Changed. You'll then be writing the method txtTickets_TextChanged. This method has just 1 line; simply call clearTicketsRadioButtons().

Clear Payment RadioButtons if txtPayment is Changed
If a change is made to txtPayment, you want to clear (uncheck) the RadioButtons in GroupBoxMoney. You don't want a number to be written in txtPayment and have a RadioButton checked.
From the left dropdown menu, choose txtPayment. From the right dropdown menu, choose Text Changed. You'll then be writing the method txtPayment_TextChanged. This method has just 1 line; simply call clearPaymentRadioButtons().

Clear a TextBox if a RadioButton is Clicked
You need to have code that causes a RadioButton to be checked when it is clicked on. The following method does this for the RadioButtons in GroupBoxTickets. The method also clears txtNumTickets if a RadioButton is clicked. This code is complete and you should copy it into your program:

Private Sub GroupBoxTicketsClicked(sender As Object, e As EventArgs) Handles RadioButton1.Click, RadioButton2.Click, RadioButton3.Click, RadioButton4.Click, RadioButton5.Click, RadioButton6.Click
    txtNumTickets.Text = ""
    Dim rb As RadioButton
    rb = sender
    rb.Checked = True
End Sub

The following is a similar method for GroupBoxPayment. This is complete and you should copy it into your program:

Private Sub GroupBoxPaymentClicked(sender As Object, e As EventArgs) Handles radPayment1.Click, radPayment2.Click, radPayment3.Click, radPayment4.Click
txtPayment.Text = ""
Dim rb As RadioButton
rb = sender
rb.Checked = True
End Sub

Check Money and Print the Ticket
You can have a method checkMoneyAndPrintTicket() that checks whether the customer's payment is adequate to cover the cost of the tickets. If it is, a ticket is printed. If it's not, a message displays that the money is insufficient.
Declare a String 'result' and a double 'change'.
Calculate the variable 'cost' as the product of 9.50 and 'numTickets'.
In an IF statement, see if 'cost' exceeds 'payment'. If it does:

In the 'Else' of the IF statement (which runs if 'cost' is less than or equal to 'payment'):
- set up an inner IF statement that checks whether or not the user has selected a movie. This can be done by seeing if 'movie' is empty. If it is not empty, then:

(If the user has not yet selected a movie, you don't have to do anything.)

Print the Ticket
Double-click on Button1 to write the code for when the user clicks Button1. Simply call these 3 methods:
- getPayment()
- getNumTickets()
- checkMoneyAndPrintTicket()
For example, you can write: Call getPayment()

 

Demo

You can download my version of this program here, to get an idea of what your program will do when it is complete. Right-click on the link and choose 'Save Target As' to download ticketPrinter.zip. Once the file is downloaded, double-click on it to unzip it. Then click on 'ticketPrinter' (with file type 'Application') to run the program.