- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
160 Chapter 4 WRITING AND USING PROCEDURES
Functions can be called from within expressions, as the following statement shows:
MsgBox(“40 degrees Celsius are “ & Fahrenheit(40).ToString & _ “ degrees Fahrenheit”)
Notice that the ToString method applies to the numeric value returned by the function, and you need not implement it as part of your function. All numeric types provide the ToString method, which converts the numeric value to a string.
Suppose the function CountWords() counts the number of words and the function CountChars() counts the number of characters in a string. The average length of a word could be calculated as follows:
Dim longString As String, avgLen As Double longString = TextBox1.Text
avgLen = CountChars(longString) / CountWords(longString)
The first executable statement gets the text of a TextBox control and assigns it to a variable, which is then used as an argument to the two functions. When the second statement executes, Visual Basic first calls the functions CountChars() and CountWords() with the specified arguments and then divides the results they return.
You can call functions in the same way that you call subroutines, but the result won’t be stored anywhere. For example, the function Convert() may convert the text in a textbox to uppercase and return the number of characters it converts. Normally, you’d call this function as follows:
nChars = Convert()
If you don’t care about the return value—you only want to update the text on a TextBox control— you would call the Convert() function with the following statement.
Convert()
VB6 VB.NET
The Call statement of VB6 has disappeared. Also, the parentheses around the argument list are mandatory, even if the subroutine or function doesn’t accept any arguments. You can no longer call a subroutine with a statement like
ConvertText myText
You must enclose the arguments in a pair of parentheses:
ConvertText(myText)
Arguments
Subroutines and functions aren’t entirely isolated from the rest of the application. Most procedures accept arguments from the calling program. Recall that an argument is a value you pass to the procedure and on which the procedure usually acts. This is how subroutines and functions communicate with the rest of the application.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
ARGUMENTS 161
Functions also accept arguments—in many cases, more than one. The function Min(), for instance, accepts two numbers and returns the smaller one:
Function Min(ByVal a As Single, ByVal b As Single) As Single
Min = IIf(a < b, a, b)
End Function
IIf() is a built-in function that evaluates the first argument, which is a logical expression. If the expression is True, the IIf() function returns the second argument. If the expression is False, the function returns the third argument.
To call this function use a few statements like the following:
Dim val1 As Single = 33.001 Dim val2 As Single = 33.0011 Dim smallerVal as Single smallerVal = Min(val1, val2)
Console.Write(“The smaller value is “ & smallerVal)
If you execute these statements (place them in a button’s Click event handler), you will see the following on the Output window:
The smaller value is 33.001
If you attempt to call the same function with two double values, as in a statement like the following:
Console.WriteLine(Min(3.33000000111, 3.33000000222))
you will see the value 3.33 in the Output window. The compiler converted the two values from Double to Single data type and returned one of them. Which one is it? It doesn’t make a difference, because when converted to Single, both values are the same.
Interesting things will happen if you attempt to use the Min() function with the Strict option turned on. Insert the statement Option Strict On at the very beginning of the file. First, the editor will underline the statement that implements the Min() function—the IIf() function. The IIf() function accepts two Object variables as arguments, and you can’t call it with Single or Double values. The Strict option prevents the compiler from converting numeric values to objects. To use the IIf() function with the Strict option, you must change its implementation as follows:
Function Min(ByVal a As Object, ByVal b As Object) As Object
Min = IIf(Val(a) < Val(b), a, b)
End Function
Argument-Passing Mechanisms
One of the most important issues in writing procedures is the mechanism used to pass arguments. The examples so far have used the default mechanism: passing arguments by value. The other mechanism is passing them by reference. Although most programmers use the default mechanism, it’s important to know the difference between the two mechanisms and when to use each.
Passing Arguments by Value
When you pass an argument by value, the procedure sees only a copy of the argument. Even if the procedure changes it, the changes aren’t permanent. The benefit of passing arguments by value is that
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
162 Chapter 4 WRITING AND USING PROCEDURES
the argument values are isolated from the procedure, and only the code segment in which they are declared can change their values. This is the default argument-passing mechanism in VB.NET.
To specify the arguments that will be passed by value, use the ByVal keyword in front of the argument’s name. If you omit the ByVal keyword, the editor will insert it automatically, since it’s the default option. To declare that the Degrees() function’s arguments are passed by value, use the ByVal keyword in the argument’s declaration as follows:
Function Degrees(ByVal Celsius as Single) As Single
Degrees = (9 / 5) * Celsius + 32
End Function
To see what the ByVal keyword does, add a line that changes the value of the argument in the function:
Function Degrees(ByVal Celsius as Single) As Single
Degrees = (9 / 5) * Celsius + 32
Celsius = 0
End Function
Now call the function as follows:
CTemp = InputBox(“Enter temperature in degrees Celsius”) MsgBox(CTemp.ToString & “ degrees Celsius are “ & Degrees((CTemp)) & _
“ degrees Fahrenheit”)
If the value entered in the InputBox is 32, the following message is displayed:
32 degrees Celsius are 89.6 degrees Fahrenheit
Replace the ByVal keyword with the ByRef keyword in the function’s definition and call the function as follows:
Celsius = 32.0
FTemp = Degrees(Celsius)
MsgBox(Celsius.ToString & “ degrees Celsius are “ & FTemp & _ “ degrees Fahrenheit”)
This time the program displays the following message:
0 degrees Celsius are 89.6 degrees Fahrenheit
When the Celsius argument was passed to the Degrees() function, its value was 32. But the function changed its value, and upon return it was 0. Because the argument was passed by reference, any changes made by the procedure affected the variable permanently. When the calling program attempted to use it, the variable had a different value than expected.
Note When you pass arguments to a procedure by reference, you’re actually passing the variable itself. Any changes made to the argument by the procedure will be permanent. When you pass arguments by value, the procedure gets a copy of the variable, which is discarded when the procedure ends. Any changes made to the argument by the procedure won’t affect the variable of the calling program.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
ARGUMENTS 163
Note When you pass an array as argument to a procedure, the array is always passed by reference—even if you specify the ByVal keyword. The reason for this is that it would take the machine some time to create a copy of the array. Since the copy of the array must also live in memory, passing too many arrays back and forth by value would deplete your system’s memory.
Passing Arguments by Reference
Passing arguments by reference gives the procedure access to the actual variable. The calling procedure passes the address of the variable in memory so that the procedure can change its value permanently. With VB6, this was the default argument-passing mechanism, but this is no longer the case.
Start a new Visual Basic project and enter the following function definition in the form’s code window:
Function Add(ByRef num1 As Integer, ByRef num2 As Integer) As Integer Add = num1 + num2
num1 = 0 num2 = 0 End Function
This simple function adds two numbers and then sets them to zero.
Next, place a Command button on the form and enter the following code in the button’s Click event:
Dim A As Integer, B As Integer
A = 10
B = 2
Dim Sum As Integer
Sum = Add(A, B)
Console.WriteLine(A)
Console.WriteLine(B)
Console.WriteLine(Sum)
This code displays the following results in the Output window:
0
0
12
The changes made to the function’s arguments take effect even after the function has ended. The values of the variables A and B have changed value permanently.
Now change the definition of the function by inserting the keyword ByVal before the names of the arguments, as follows:
Function Add(ByVal num1 As Integer, ByVal num2 As Integer) As Integer
With this change, Visual Basic passes copies of the arguments to the function. The rest of the program remains the same. Run the application, click the button, and the following values display in the Output window:
10
2
12
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
164 Chapter 4 WRITING AND USING PROCEDURES
The function has changed the values of the arguments, but these changes remain in effect only in the function. The variables A and B in the Button1_Click event handler haven’t been affected.
As you type the names of the arguments in the declaration of a subroutine or function, the editor inserts automatically the ByVal keyword if you omit it (unless, of course, you specify the ByRef keyword). In general, you pass arguments by reference only if the procedure has reason to change its value. If the values of the arguments are required later in the program, you run the risk of changing their values in the procedure.
Returning Multiple Values
If you want to write a function that returns more than a single result, you will most likely pass additional arguments by reference and set their values from within the function’s code. The following function calculates the basic statistics of a data set. The values of the data set are stored in an array, which is passed to the function by reference.
The Stats() function must return two values, the average and standard deviation of the data set. In a real-world application, a function like Stats() should calculate more statistics than this, but this is just an example to demonstrate how to return multiple values through the function’s arguments. Here’s the declaration of the Stats() function:
Function Stats(ByRef Data() As Double, ByRef Avg As Double, _
ByRef StDev As Double) As Integer
The function returns an integer, which is the number of values in the data set. The two important values calculated by the function are returned in the Avg and StDev arguments.
Function Stats(ByRef Data() As Double, ByRef Avg As Double, _ ByRef StDev As Double) As Integer
Dim i As Integer, sum As Double, sumSqr As Double, points As Integer points = Data.Length
For i = 0 To points - 1 sum = sum + Data(i)
sumSqr = sumSqr + Data(i) ^ 2 Next
Avg = sum / points
StDev = System.Math.Sqrt(sumSqr / points - Avg ^ 2) Return(points)
End Function
To call the Stats() function from within your code, set up an array of doubles and declare two variables that will hold the average and standard deviation of the data set:
Dim Values(100) As Double
‘ Statements to populate the data set Dim average, deviation As Double
Dim points As Integer
points = Stats(Values, average, deviation) Console.WriteLine points & “ values processed.” Console.WriteLine “The average is “ & average & “ and” Console.WriteLine “the standard deviation is “ & deviation
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |