Let me take a few moments here before getting into the project code to discuss some issues that don't really fit into any particular chapter discussion, but that you might end up using a lot in your own applications.
The MsgBox Method
Although I've used it on practically every page of this book so far, I have never formally introduced you to the MsgBox method. Part of the Microsoft.VisualBasic namespace, MsgBox is a carryover from the MsgBox function in the original release of Visual Basic. It displays a simple message window, including a selection of response buttons and an optional icon. As a function, it returns a code indicating which button the user clicked to close the form, one of the MsgBoxResult enumeration values. The syntax is:
Public Function MsgBox(ByVal Prompt As Object, _ Optional ByVal Buttons As _ MsgBoxStyle = MsgBoxStyle.OKOnly, _ Optional ByVal Title As Object = Nothing) _ As MsgBoxResult
The Prompt parameter accepts a string for display in the main body of the dialog; Buttons indicates which buttons, icons, and other settings to use when displaying the dialog; and Title accepts a custom window title if you want something other than the application title to appear. The following statement displays the window in Figure 8-2.
Dim result As MsgBoxResult = MsgBox( _ "It's safe to click; the computer won't explode.", _ MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question, _ "Click Something")
Figure 8-2. Communicating an important message
The MsgBox function is considered to be an intrinsic part of the language. But as a member of the Microsoft.VisualBasic namespace, it's valid within the Visual Basic language only. If you were to do some .NET coding in C#, you would need to find another way to display a message box. That way is through the MessageBox.Show method. It works pretty much like the MsgBox function, but its second and third arguments are reversed. Some .NET conformists insist that MsgBoxand anything that appears in the Microsoft.VisualBasic namespacemust be spurned in favor of class library alternatives. Personally, I find it to be a preference choice, but you may encounter just such a person insisting that your code is substandard. You can read my views about such tactics in Chapter 25, "Project Complete."
Programs are designed to do a lot of thinking, and sometimes they think so much, they pretty much lock up the computer. This is especially true of Visual Basic methods that perform a lot of database-heavy transactions, one right after another. The system defers less-important screen updates so that more important data processing code can occur first. That's great, but sometimes the user thinks, "This stupid computer's dead again," and pulls the plug. If the screen would simply provide better updates, the user might be more patient.
Each control on your form (and the form itself) includes a Refresh method, but it can be a bother to constantly refresh everything. And refreshing the display wouldn't do much to enable the "Cancel" button that you want your user to click to abort all that lovely data processing. To make life easier, Visual Basic includes a DoEvents method. When called, the current method's code pauses temporarily, and messages in the thread's incoming message queue are processed, including "paint" (screen update) messages. DoEvents is part of the My namespace, and is used as a standalone statement.
Be warned that overuse of DoEvents can slow down your application, and can lead to problems related to an event being called too many times. In general, it should be used only in a processing-intensive block of code, and then it should be spread out so that it is called only a few times per second at the most.
Any method can enable optional arguments, and the calling code can choose to include or exclude those arguments. But what if you wanted to add an unlimited number of optional arguments to a method? How could you write, for instance, a function that would return the average of all supplied arguments, with no limits on the number of arguments? Although you could accept an array variable with the source data values, you could also use a parameter array argument, also called a "ParamArray" argument.
As with optional arguments, ParamArray arguments must appear at the end of a method's argument list, and there can be only one, because one is more than enough for any method. Parameter array arguments use the ParamArray keyword just before the argument name.
Public Function CalculateAverage( _ ParamArray sourceData() As Decimal) As Decimal ' ----- Calculate the average for a set of numbers. Dim singleValue As Decimal Dim runningTotal As Decimal = 0@ If (sourceData.GetLength(0) = 0) Then Return 0@ Else For Each singleValue In sourceData runningTotal += singleValue Next singleValue Return runningTotal / sourceData.GetLength(0) End If End Function
Calls to the CalculateAverage function now accept any number of decimal values.
MsgBox(CalculateAverage(1, 2, 3, 4, 5)) ' Displays: 3