- •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
BUILDING THE MINIMAL CLASS 331
you must make it part of the project by adding its icon to the Toolbox, if it’s not already there. To use a class in your code, you must import the file that implements the class (this is a DLL file). To manipulate a control from within your code, you call its properties and methods. You do the same with classes. Finally, you program the various events raised by the controls to interact with the users of your applications. Most classes don’t expose any events, since the user can’t interact with them, but some classes do raise events, which you can program just as you program the events of a Windows control. Using classes is not new to you, and many of the concepts presented in this chapter are not new to you either.
In Chapter 3, I mentioned briefly that a class combines code and data. You have probably noticed this already in the last couple of chapters. The System.Integer class, for example, stores an integer value and knows how to process it. Variables in VB.NET are not just areas in memory you can access by name; they’re instances of the corresponding classes. The array is a better example. The role of the array is to store sets of data. In addition to holding the data, the Array class also knows how to process them—how to retrieve an element, how to extract a segment of the array, even how to sort its elements. All these operations require a substantial amount of code. The data stored in the array and the code that implements the properties and the methods of the array are hidden from you, the developer. You can instruct the array to perform certain tasks. When you call the Sort method, you’re telling the array to execute some code that will sort the elements of the array. The developer doesn’t know how the data are stored in the array, or how the Sort method works. In the following section, you’ll see how data and code coexist in a class and how you can manipulate the data through the properties and methods exposed by the class. Let’s start by building a custom class and then using it in our code.
Building the Minimal Class
Our first example is the Minimal class; we’ll start with the minimum functionality and keep adding features to it. The name of the class can be anything—just make sure it’s suggestive of the class’s functionality.
A Class may reside in the same file as a Form, but it’s customary to implement custom classes in a separate module, a Class module. You can also create a Class project, which contains just a class. However, a class doesn’t run on its own, and you can’t test it without a form. You can create a Windows application, add the class to it, and then test it by adding the appropriate code to the form. After debugging the class, you can remove the test form and use the class with any project. Since the class is pretty useless outside the context of an application, in this chapter I will use Windows applications and add a class to them.
Start a new project and name it SimpleClass (or open the project by that name on the CD). Then create a new class by adding a Class item to your project. Right-click the project’s name in the Solution Explorer window and, from the context menu, select Add Add Class. In the dialog box that pops up, select the Class icon and enter a name for the class. Set the class’s name to Minimal, as shown in Figure 8.1.
The code that implements the class will reside in the Minimal.vb file, and we’ll use the existing form to test our class. After you have tested and finalized the class’s code, you no longer need the form and you can remove it from the project.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
332 Chapter 8 BUILDING CUSTOM CLASSES
Figure 8.1
Adding a Class item to a project
When you open the class by double-clicking its icon in the Project Explorer window, you will see the following lines in the code window:
Public Class Minimal
End Class
You can also create a class in the same file as the application’s form. To do so, enter the Class keyword followed by the name of the class, after the existing End Class. The editor will insert the matching End Class for you. At this point, you already have a class, even though it doesn’t do anything. Switch back to the Form Designer, add a button to the test form, and insert the following code in its Click event handler:
Dim obj1 As Minimal()
Press Enter and, on the following line, type the name of the variable, obj1, followed by a period. You will see a list of the methods your class exposes already:
Equals
GetHashCode
GetType
ReferenceEqual
ToString
These methods are provided by the Common Language Runtime (CLR). You don’t have to supply any code for these methods. They don’t expose any real functionality; they simply reflect how VB handles all classes. To see the kind of functionality these methods expose, enter the following lines in the Button’s Click event handler and then run the application:
Dim obj1 As New Minimal()
Console.WriteLine(obj1.ToString)
Console.WriteLine(obj1.GetType)
Console.WriteLine(obj1.GetHashCode)
Dim obj2 As New Minimal()
Console.WriteLine(obj1.Equals(obj2))
Console.WriteLine(Minimal.ReferenceEquals(obj1, obj2))
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
BUILDING THE MINIMAL CLASS 333
The following lines will be printed on the Output window:
SimpleClass.Minimal
SimpleClass.Minimal
18 False False
As you can see, the name of the object is the same as its type. This is all the information about your new class that’s available to the CLR. Shortly you’ll see how you can implement your own ToString method and return another value. The hash value of the obj1 variable happens to be 18, but this is of no consequence.
The next line tells you that two variables of the same type are not equal. But why aren’t they equal? We haven’t differentiated them at all, yet they’re different because they point to two different objects and the compiler doesn’t know how to compare them. All it can do is figure out whether they point to the same object. To understand how objects are compared, add the following statement after the line that declares obj2:
obj2 = obj1
If you run the application again, the last statement will print True on the Output window. The Equals method checks for reference equality; that is, it returns True if both variables point to the same object (same instance of the class). If you change obj1, then obj2 will point to the new object. OK, we can’t change the object because it exposes no members that we can set to differentiate it from another object of the same type. We’ll get to that shortly.
Most classes expose a custom Equals method, which knows how to compare two objects of the same class. The custom Equals method usually compares the properties of the two instances of the class and returns True if all properties are the same. You’ll learn how to customize the default members of any class later in this chapter.
Notice the name of the class: SimpleClass.Minimal. Within the current project, you can access it as Minimal. Other projects can either import the Minimal class and access it as Minimal, or specify the complete name of the class.
Adding Code to the Minimal Class
Let’s add some functionality to our class. We’ll begin by adding a few properties and methods to perform simple text-manipulation tasks. The two properties are called property1 (a String) and property2 (a Double). To expose these two members as properties, you can simply declare them as public variables. This isn’t the best method of implementing properties, but it really doesn’t take more than declaring something as Public to make it available to code outside the class. The following line exposes the two properties of the class:
Public property1 As String, property2 As Double
The two methods are the ReverseString and NegateNumber methods. The first method reverses the order of the characters in property1 and returns the new string. The NegateNumber method returns the negative of property2. These are the simplest type of methods that don’t accept any arguments; they simply operate on the values of the properties. In just the way that properties are exposed as Public variables, methods are exposed as Public procedures (functions or subroutines).
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
334 Chapter 8 BUILDING CUSTOM CLASSES
Enter the function declarations of Listing 8.1 between the Class Minimal and End Class statements in the class’s code window (I’m showing the entire listing of the class here).
Listing 8.1: Adding a Few Members to the Minimal Class
Public Class Minimal
Public property1 As String, property2 As Double
Public Function ReverseString() As String
Return (StrReverse(property1))
End Function
Public Function NegateNumber() As Double
Return (-property2)
End Function
End Class
Let’s test what we’ve done so far. Switch back to your form and enter the lines shown in Listing 8.2 in a new button’s Click event handler. Notice that as soon as you enter the name of the obj variable and the period after it, a complete list of the class’s members, including the custom members, appears in a list box.
The obj variable is of the Minimal type and exposes the public members of the class. You can set and read its properties and call its methods. In Figure 8.2, you see a few more members than the ones added so far; we’ll extend our Minimal class in the following section. Your code doesn’t see the class’s code, just as it doesn’t see any of the built-in classes’ code. You trust that the class knows what it’s doing and does it right.
Listing 8.2: Testing the Minimal Class
Dim obj As New Minimal()
obj.property1 = “ABCDEFGHIJKLMNOPQRSTUVWXYZ” obj.property2 = 999999 Console.WriteLine(obj.ReverseString) Console.WriteLine(obj.NegateNumber)
Figure 8.2
The members of the class are displayed automatically by the IDE, as needed.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |