Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
(ebook) Visual Studio .NET Mastering Visual Basic.pdf
Скачиваний:
136
Добавлен:
17.08.2013
Размер:
15.38 Mб
Скачать

ARGUMENTS 165

Using ByRef arguments is the simplest method for a function to return multiple values. However, the definition of your functions may become cluttered, especially if you want to return more than a few values. Another problem with this technique is that it’s not clear whether an argument must be set before calling the function or not. As you will see shortly, it is possible for a function to return an array, or a custom structure with fields for any number of values.

Passing Objects as Arguments

When you pass objects as arguments, they’re passed by reference, even if you have specified the ByVal keyword. The procedure can access and modify the members of the object passed as argument, and the new value will be visible in the procedure that made the call.

The following code segment demonstrates this. The object is an ArrayList, which is an enhanced form of an array. The ArrayList is discussed in detail later in the book, but to follow this example all you need to know is that the Add method adds new items to the ArrayList, and you can access individual items with an index value, similar to an array’s elements. The Click event handler of a Button control creates a new instance of the ArrayList object and calls the PopulateList() subroutine to populate the list. Even though the ArrayList object is passed to the subroutine by value, the subroutine has access to its items:

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click Dim aList As New ArrayList()

PopulateList(aList) Console.WriteLine(aList(0).ToString) Console.WriteLine(aList(1).ToString) Console.WriteLine(aList(2).ToString)

End Sub

Sub PopulateList(ByVal list As ArrayList) list.Add(“1”)

list.Add(“2”)

list.Add(“3”) End Sub

The same is true for arrays and all other collections. Even if you specify the ByVal keyword, they’re passed by reference. A more elegant method of modifying the members of a structure from within a procedure is to implement the procedure as a function returning a structure, as explained in the section “Functions Returning Structures,” later in this chapter.

Event-Handler Arguments

In this section, we’re going to look at the implementation of event handlers as subroutines. Event handlers never return a result, so they’re implemented as subroutines. In specific, we’re going to examine the two arguments that are common to all event handlers, which pass information about the object and the action that invoked the event.

You may have noticed that the subroutines that handle events accept two arguments: sender and e. Here’s the declaration of the Click event handler for a button:

Private Sub Button1_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles Button1.Click

End Sub

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

166 Chapter 4 WRITING AND USING PROCEDURES

The sender argument conveys information about the object that initiated the event; we use this argument in our code to find out the type of the object that raised the event. The following two statements in a button’s Click event handler will print the values shown in bold on the Output window:

Console.WriteLine(sender.ToString)

System.Windows.Forms.Button, Text: Button1

Console.WriteLine(sender.GetType)

System.Windows.Forms.Button

The second argument contains all the information you really need to process the event. The e argument is an object that exposes some properties, which vary depending on the type of the event and the control that raised the event. A TextBox control, for example, raises several events when a key is pressed, in addition to the events of the mouse. The information you need to process the different types of events is passed to your application through the second argument of the event handler.

Let’s examine the members of this argument for two totally different event types. The e argument passed to the Click event handler has no special properties. All the information you really need is that a button was clicked and nothing more. The location of the pointer, for example, doesn’t make any difference in your code, neither do you care about the status of the various control keys. Regardless of whether the Alt or the Shift key was down or not when the left mouse button was clicked, your application will be notified about the Click event. If you want to capture the state of the control keys and react differently depending on their status, you must program the handler of the MouseDown or MouseUp events. These events are raised when the mouse is pressed or released and are independent of the Click event.

The Mouse Events

Every time you click the mouse, a series of events is triggered. When you perform a single click, your application receives a MouseDown event, then a Click event, and then a MouseUp event. You get mouse events even as you scroll the mouse over a control: the MouseEnter when the mouse enters the control, a series of MouseMove events as you move the mouse over the control, a MouseHover event if you hover the mouse over the control, and a MouseLeave event as soon as the pointer gets outside the bounds of the control. Different mouse events report different information to the application through the arguments of the appropriate event handler, and this information is passed to your application in the form of properties of the e argument. The e argument of most mouse events provides the following properties.

Button

This property returns the button that was pressed, and its value is one of the members of the MouseButtons enumeration: Left, Middle, None, Right, XButton1, and XButton2. The last two members of the enumeration are for five-button mice and correspond to the two side buttons. The Button property is present in events that involve the button of the mouse. The e argument of the Click and DoubleClick events, however, doesn’t provide a Button property; these two events can only be triggered with the left button.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

ARGUMENTS 167

Clicks

This property returns the number of times the mouse button was pressed and released. Its value is 1 for a single click and 2 for a double-click. You can’t click a control three times—as soon as you click it for the second time, a double-click event will be raised.

Delta

This property is used with wheel mice; it reads the number of detents (that is, notches or stops) that the mouse wheel was rotated. You can use this property to figure out how much a TextBox control was scrolled (or any other control that can be scrolled with a scrollbar).

X, Y

These two properties return the coordinates of the pointer at the moment the mouse button was pressed (in the MouseDown event) or released (in the MouseUp event). The coordinates are expressed in pixels in the client’s area. If you click a Button control at the very first pixel (its top-left corner), the X and Y properties will be 0.

The same properties are exposed by both the MouseDown and MouseUp events. Notice that these two events are fired regardless of which button was pressed—unlike the Click and DoubleClick events, which can’t be triggered with a button other than the left one.

The X and Y properties may be different for the MouseDown and MouseUp events. For example, you can press a button and hold it down while you move the pointer around. When you release the button, its coordinates will be different than the coordinates reported by the MouseDown event. If you move the mouse outside the control in which you pressed the button, the coordinates may exceed the dimensions of the control, or even be negative. They are the distances of the pointer, at the moment you released the button, from the top-left corner of the control.

Insert the following code in a Button’s MouseDown and MouseUp event handlers:

Private Sub Button1_MouseDown(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) _

Handles Button1.MouseDown

Console.WriteLine(“Button pressed at “ & e.X & “, “ & e.Y)

End Sub

Private Sub Button1_MouseUp(ByVal sender As Object, _

ByVal e As System.Windows.Forms.MouseEventArgs) _

Handles Button1.MouseUp

Console.WriteLine(“Button released at “ & e.X & “, “ & e.Y)

End Sub

If you press and release the mouse at a single point, both handlers will report the same point. If you move the pointer before releasing the button, you will see four values like the following:

Button pressed at 63, 16

Button released at –107, -68

As you can guess, the mouse button was pressed while the pointer was over the Button control, and it was released after the pointer was moved to the left and above the Button control.

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

168 Chapter 4 WRITING AND USING PROCEDURES

The Key Events

The TextBox control recognizes the usual mouse events, but the most important events in programming the TextBox (or other controls that accept text) are the key events, which are raised when a key is pressed, while the control has the focus. The KeyPress event is fired every time a key is pressed.

This event reports the key that was pressed. You can have finer control over the user’s interaction with the keyboard with the KeyDown and KeyUp events, which are fired when a key is pressed and released respectively. The KeyDown event handler’s definition is:

Private Sub TextBox1_KeyDown(ByVal sender As Object, _

ByVal e As System.Windows.Forms.KeyEventArgs) _

Handles TextBox1.KeyDown

The second argument of the KeyDown and KeyUp event handlers provides information about the status of the keyboard and the key that was pressed through the following properties.

Alt, Control, Shift

These three properties return a True/False value indicating whether one or more of the control keys were down when the key was pressed.

KeyCode

The KeyCode property returns the code of the key that was pressed, and its value can be one of the members of the Keys enumeration. This enumeration contains a member for all keys, including the mouse keys, and its members are displayed in a drop-down list when you need them. Notice that each key has its own code, which usually corresponds to two different characters. The “a” and “A” characters, for example, have the same code, the KeysA member. The code of the key “0” on the numeric keypad is the member Key0, and the function key F1 has the code KeyF1.

KeyData

This property returns a value that identifies the key pressed, similar to the KeyCode property, but it also distinguishes the character or symbol on the key. The KeyCode for the 4 key is 52, regardless of whether it was pressed with the Shift key or not. The same KeyCode value applies to the $ symbol, because they’re both on the same key. The KeyData values for the same two characters are two long values that include the status of the control keys. The value of the KeyData property is a member of the Keys enumeration.

KeyValue

This property returns the keyboard value for the key that was pressed. It’s usually the same as the KeyData value, but certain keys don’t report a value (the control keys, for example, don’t report a KeyValue).

Passing an Unknown Number of Arguments

Generally, all the arguments that a procedure expects are listed in the procedure’s definition, and the program that calls the procedure must supply values for all arguments. On occasions, however, you may not know how many arguments will be passed to the procedure. Procedures that calculate averages or, in general, process multiple values can accept a few to several arguments whose count is not

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com

ARGUMENTS 169

known at design time. In the past, programmers had to pass arrays with the data to similar procedures. Visual Basic supports the ParamArray keyword, which allows you to pass a variable number of arguments to a procedure.

Let’s look at an example. Suppose you want to populate a ListBox control with elements. To add an item to the ListBox control, you call the Add method of its Items collection as follows:

ListBox1.Items.Add(”new item”)

This statement adds the string “new item” to the ListBox1 control.

If you frequently add multiple items to a ListBox control from within your code, you can write a subroutine that performs this task. The following subroutine adds a variable number of arguments to the ListBox1 control:

Sub AddNamesToList(ParamArray ByVal NamesArray() As Object)

Dim x As Object

For Each x In NamesArray

ListBox1.Items.Add(x)

Next x

End Sub

This subroutine’s argument is an array prefixed with the keyword ParamArray. This array holds all the parameters passed to the subroutine. To add items to the list, call the AddNamesToList() subroutine as follows:

AddNamesToList(“Robert”, “Manny”, “Renee”, “Charles”, “Madonna”)

If you want to know the number of arguments actually passed to the procedure, use the Length property of the parameter array. The number of arguments passed to the AddNamesToList() subroutine is given by the expression:

NamesArray.Length

The following loop goes through all the elements of the NamesArray and adds them to the list:

Dim i As Integer

For i = 0 to NamesArray.GetUpperBound(0)

ListBox1.Items.Add(NamesArray(i))

Next i

If you want to use the array’s Length property, write a loop like the following:

Dim i As Integer

For i = 0 to NamesArray.Length - 1

ListBox1.Items.Add(NamesArray(i))

Next i

A procedure that accepts multiple arguments relies on the order of the arguments. To omit some of the arguments, you must use the corresponding comma. Let’s say you want to call such a procedure and specify the first, third, and fourth arguments. The procedure must be called as:

ProcName(arg1, , arg3, arg4)

Copyright ©2002 SYBEX, Inc., Alameda, CA

www.sybex.com