Tuesday, April 8, 2008

Structures

Instead of using parallel or 2-dimensional arrays for storing various information that we would like to manipulate. For example, universities have various information about them that is universal. Each university has the following properties:

  • Name
  • State in which the university is located
  • Date that the university was founded
  • Population


Of course there are many more things that universities have, but this is a start.

Now we could use parallel arrays to store this information (like in our ATM project). Doing so, would mean that we would have 4 arrays to store the above information and that we could use the same index to reference information for a particular university:

Dim uName(3) As String
Dim uState(3) As String
Dim uFounded(3) As String
Dim uPopulation(3) As String

Let's say that we set the following:

uName(1) = "Queens College"
uState(1) = "NY"
uFounded(1) = "1960" 'I'm not sure about the date
uPopulation(1) = "5,000" 'Or the population :-)

So all of Queens College's information is accessible by accessing index 1 of each array. Thus the parallel Nature.

But suppose that we do not want to keep track of four arrays. We could then create a Structure or a container to keep all of this information in one place:

Structure uInfo
Dim name As String
Dim state As String
Dim founded As String
Dim population As String
End Structure

Now we have created our own type and we can declare a variable of this type like this:

Dim college As uInfo

In order to set (or use) any property of colleges, we use the ``dot'' method:

college.name = "Queens College"
college.state = "NY"
college.founded = "1960"
college.population = "5,000"


Declaring an Array of type uInfo

We can declare arrays of any type, including our own defined types.

Dim colleges(10) As uInfo
colleges(0).name = "Queens College"
colleges(0).state = "NY"
colleges(0).founded = "1960"
colleges(0).population = "5,000"

The resulting array will look like (except up to 10):
        0          1    2 ...
+---------------+----+----+
| Queens College| | |
+---------------+----+----+
| NY | | |
+---------------+----+----+
| 1960 | | |
+---------------+----+----+
| 5,000 | | |
+---------------+----+----+


You can see that every cell is broken up into 4 parts that contain the items from the structure itself.

Of course if we had an array of things, it would make more sense to take in the information from a file:

For i As Integer = 0 To 10
colleges(i).name = sr.Readline()
colleges(i).state = sr.Readline()
colleges(i).founded = sr.Readline()
colleges(i).population = sr.Readline()
Next

Student Grades Example

Today we talked about dealing with student grades using arrays. We would have an array that would hold the students' identifying information (such as name or ID number) and then arrays for all of the students' grades. Remember, these are called Parallel Arrays.

Example:

Public Class Form1
'Global Variables:
Dim students(5) As String
Dim hw1(5) As Double
Dim hw2(5) As Double
Dim hw3(5) As Double
...
...


We have declared these arrays as Global so that we will be able to use them in all subroutines, and also so that we will not loose the information stored in them for the duration of the program. Here are what the resulting arrays look like:

students()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw1()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw2()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw3()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+


As we can see, Student1's information will reside in index 1 of all the arrays.

Code

We wrote two subroutines, one to get the information from the user and one to find and print the information for a particular student.

Here is the code for getting the student information:

Sub form_load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
hw1(i) = CDbl(InputBox("Enter homework 1:"))
hw2(i) = CDbl(InputBox("Enter homework 2:"))
hw3(i) = CDbl(InputBox("Enter homework 3:"))
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
listbox1.Items.Add(hw1(i))
listbox1.Items.Add(hw2(i))
listbox1.Items.Add(hw3(i))
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


2-Dimensional Conversion

We can convert the 1-dimensional grade parallel arrays into a two dimensional array. The names of the students must remain a separate 1-dimensional array, however since its type is different. Here are the declarations:


Public Class Form1
'Global Variables:
Dim students(5) As String

Declare hw() with 3 rows and 5 columns:
Dim hw(3,5) As Double
...
...

Resulting in the following arrays:

students()
0 1 2 3 4
+----+----+----+----+----+
| | | | | |
+----+----+----+----+----+

hw()
0 1 2 3 4
+----+----+----+----+----+
0 | | | | | |
+----+----+----+----+----+
1 | | | | | |
+----+----+----+----+----+
2 | | | | | |
+----+----+----+----+----+


Rewritten Code

In the hw() array, each row represents a HW grade and each column represents the grades for each student. Now we will rewrite our subroutines:

Sub Form_Load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
hw(0,i) = CDbl(InputBox("Enter homework 1:"))
hw(1,i) = CDbl(InputBox("Enter homework 2:"))
hw(2,i) = CDbl(InputBox("Enter homework 3:"))
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
listbox1.Items.Add(hw(0,i))
listbox1.Items.Add(hw(1,i))
listbox1.Items.Add(hw(2,i))
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


If we wanted to reduce the three lines dealing with the HW grades into one line, we could add another For loop to loop through the grades:

Sub Form_Load()
For i As Integer=0 To students.GetUpperBound(0)
students(i) = InputBox("Enter student " & _
CStr(i) & "'s name:")
For j As Integer=0 To hw.GetUpperBound(0)
hw(j,i) = CDbl(InputBox("Enter homework " & CStr(j)))
Next
Next
End Sub


Here is the code for a linear search of a student:

Sub btnSearch_Click()
Dim sname As String
Dim found As Boolean = False
sname = InputBox("Enter student's name:")
For i As Integer = 0 To students.GetUpperBound(0)
If sname = students(i) Then
For j As Integer=0 To hw.GetUpperBound(0)
listbox1.Items.Add(hw(j,i))
Next
found = True
Exit For

End If
Next


If Not found Then
MsgBox("Student not found",,"")
End If
End Sub


.GetUpperBound

Remember for 1-dimensional arrays the .GetUpperBound() function returns the number of the last possible index so:
   students.GetUpperBound(0)

returns 4.

For 2-dimensional arrays we have two indeces in which we are interested: one that indicates the highest index of rows, and one that indicates the highest index of columns. Therefore there are two possible GetUpperBound() calls:

'Get the last index of rows
hw.GetUpperBound(0)
'Get the last index of columns
hw.GetUpperBound(1)

We have used this in our rewritten subroutines above.

Monday, April 7, 2008

mp3 Files in VB .NET


You can play mp3 files in VB .NET also. The link above shows how to add a Windows Media Player to your project and to hide if you like. Otherwise you can show the player like shown at left.

You only have to change one line of code if you want it to allow the user to search for files (shown in red):

Private Sub Button1_Click(...)

Const DATA_FILE_EXTENSION As String = ".mp3"
Dim dlgFileDialog As New OpenFileDialog
With dlgFileDialog
.Filter = DATA_FILE_EXTENSION & _
" files (*" & DATA_FILE_EXTENSION & "|*" & _
DATA_FILE_EXTENSION

.FilterIndex = 1
.RestoreDirectory = True
If .ShowDialog() = Windows.Forms.DialogResult.OK Then
'Play the sound file
Me.AxWindowsMediaPlayer1.URL = dlgFileDialog.FileName
End If
End With

End Sub

Using Two Forms

Since there is some confusion about how to use two forms, I have made a video to help clear this up. First of all you have to add a second form to your project before you can use it. To do this, go to:

-> Projects
--> Add Windows Form
---> Add

Then in the Solution Explorer [usually top right] you should see two forms. You can double click one of them to begin design on it. So you have to double click ``Form2'' in order to add things to it. You will have to add a listbox to it.

From form1, you have to add one button. You have to program the button so that it will show form2.

When you run the program, only the first form will be shown by default. Therefore, you will have to manually make the second form appear by writing the following code in the button:

Form2.Show()

If you want the first form to disappear, you will have to do so manually by writing the following code:

Me.Hide()

Notice that it does not say ``Form1.Hide().'' This is because a form can only refer to itself using ``Me'' kind of like in English. You wouldn't talk about yourself in the third person, would you?

In order to skip lines you can simply Add nothing to the listbox:

Form2.Listbox1.Items.Add("") 'Skips a line

Since you will be adding several lines, you may want to use the With option:

With Form2.Listbox1.Items
.Add("Business Expense Report")
.Add("")
.Add("Information for Conference")
.Add(txtBox1.Text)
.Add(txtBox2.Text & " in " & txtBox3.Text)
.Add("")
...etc...
End With


Video of Two Forms
You may click on this link, where you can watch it full screen.

Extras - Images

We learned that we can add images to our projects by changing the BackgroundImage property for the form, or the Image property for other objects:

Photo Sharing and Video Hosting at Photobucket

Photo Sharing and Video Hosting at Photobucket

For the BackgroundImage, we can also set the image to be Tiled or Stretched however we like.

We also learned that we could change the images as the program runs. For example to set the button image to something else when it is clicked, we can write inside the Button_Click() subroutine:

Button.Image = Image.FromFile("nameofnewimagefile.jpg")


If we place our image files in the debug folder we can simply write the name of the file without having to put the entire path:

Photo Sharing and Video Hosting at Photobucket

Suppose we want to write a program that will display pictures of different albums depending on which button is clicked. An example is below:

Photo Sharing and Video Hosting at Photobucket

We could use the following code:

Private Sub Btncat_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnCat.Click
Me.BackgroundImage = Image.FromFile("cat.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch
End Sub

Private Sub BtnDog_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnDog.Click
Me.BackgroundImage = Image.FromFile("dog.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch
End Sub

Private Sub BtnIguana_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnIguana.Click
Me.BackgroundImage = Image.FromFile("iguana.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch

End Sub


Private Sub BtnRandom_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles btnRandom.Click
Dim randnum As New Random, temp As Integer
temp = randnum.Next(1, 4)
Select Case temp
Case 1
Me.BackgroundImage = Image.FromFile("iguana.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch
Case 2
Me.BackgroundImage = Image.FromFile("cat.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch
Case 3
Me.BackgroundImage = Image.FromFile("dog.jpg")
Me.BackgroundImageLayout = ImageLayout.Stretch
End Select
End Sub

Extras - Sound

Below is the code for the sound. You will have to replace the red text below with the sound file's name (remember that if you put the sound files in your debug folder you can access it with only the name and not the entire path). Note: This only works with .wav files:


'Alex Maureau, Queens College
'Credits:
'http://www.codeproject.com/vb/net/SoundClass.asp
'by Angelo Cresta


Imports System
Imports System.Runtime.InteropServices
Imports System.Resources
Imports System.IO

Public Class Sound


Declare Auto Function PlaySound Lib "winmm.dll" (ByVal name _
As String, ByVal hmod As Integer, _
ByVal flags As Integer) As Integer

Public Const SND_SYNC = &H0 'play synchronously
Public Const SND_ASYNC = &H1 'play asynchronously
Public Const SND_LOOP = &H8 'play with a loop

Public Shared Sub PlayWaveFile( _
ByVal fileWaveFullPath As String)
Try
PlaySound(fileWaveFullPath, 0, SND_ASYNC)
Catch
End Try
End Sub
End Class

Thursday, April 3, 2008

Arrays

We learned that we can use arrays as containers to hold several variables of the same type. We also learned about why we might want to use such a structure, for example, sorting 10000 names from within a file.

There are a few ways to declare an array:

  • Dim arr( size ) As Type

  • Dim arr( ) As Type = {item1, item2, ...., itemN}

  • Dim arr( ) As Type
    ...
    ...
    Redim arr( newSize )

In each of the examples above, we have the array name and the type (String, Integer, Double etc) in the declaration statement. In the first example, we indicate the size of the array with an Integer value. This will give us an array with size + 1 cells. This is because we will have subscripts/indexes/cells numbered from 0 to Size.

In the last two examples, the size is not specified in the parentheses. In the second example, the size is figured out by the compiler by looking at the number of items in the list being assigned to each cell. In the third example, the size is set sometime later using a Redim statement.

The Redim statement allows us to reset the size of the array as the program runs. It can be useful for things like taking items in from a file, where the total number of items is unknown, or expanding the array when we need to add more items to it. If we have something in the array before we call Redim, the previous items will be lost. We can save them, however, using the Preserve command:

Redim Preserve arr( newSize )

If the new size is smaller than the original size, all items after the new upperbound will be lost.

We can find the upperbound of an array at anytime with the following code:

arrayname.GetUpperBound(0)

Where arrayname is replaced by the name of your array.

Real Examples
Dim names( 10 ) As String
Dim names2( ) As String = {"Allen", "Stacy", "Simon"}


The result of these declaration statements create two arrays, names() which is of size 11 and names2() size 3. The contents of name2() look like this:
 
0 1 2
+---------+---------+---------+
| "Allen" | "Stacy" | "Simon" |
+---------+---------+---------+


Now if we want to extend names2() we can use the Redim statement:

Redim Preserve names2( 4 )
names2( 3 ) = "Max"

The contents of the array will now be:
 
0 1 2 3 4
+---------+---------+---------+--------+--------+
| "Allen" | "Stacy" | "Simon" | "Max" | |
+---------+---------+---------+--------+--------+


Notice that we used the command Preserve so that we would not loose the previous contents of our array.

Tuesday, April 1, 2008

ATM Project - Part 1

Now that we have learned about File I/O, loops and decisions we can start to work on a real project. We will create an ATM simulation and we will continue adding things to it throughout the rest of this course.

First we have to decide how an ATM works. We know that it will require the following operations:

1) Validation (pin # and account number)
2) Deposit Money
3) Withdraw Money
4) Account Status (balance etc)

We will have a text file that contains the account numbers and pins in it:
acctinfo.txt

123456789
1234
234567890
9876


This is kept in the debug folder. When the program begins,