  
Chapter 22
Object Basics
Considering that Visual Basic is not a true object-oriented language (due to Visual
Basic's lack of inheritance features), Visual Basic sure uses a lot of objects! Everything
seems to be an object in Visual Basic, including forms, windows, toolbox tools, and
ActiveX controls.
This lesson discusses several of the more advanced programming topics that surround
objects. By the time you finish this lesson, you will better understand how objects
fit into the Visual Basic environment.
The highlights of this hour include
- How to access the system objects
- What distinguishes a class from an object
- When to shortcut code with With-End blocks
- How to create your own collections
- Why OLE automation gives your application tremendous power
- How to make Word work from inside Visual Basic
The System Objects
You've worked with several Visual Basic objects already. The Printer
object is an object you use with a Print method to send output to the printer,
as in the following statement:
Printer.Print Tab(15); "Company Balance Sheet"
In addition, you've seen the Debug object when printing to the Immediate
window like this:
Debug.Print "intVar is "; intVar
In both cases, the object represents an item outside your application's scope.
The printer and the Immediate window are not your application's; therefore, Visual
Basic uses objects to represent them. The Printer object does not reference
any particular printer; rather, the Printer object references the current
Windows printer. The Debug object represents the Immediate window.
New Term: A system object is an object
defined by Visual Basic that lies outside your program's immediate scope.
The Printer and the Debug objects are system objects predefined
by the Visual Basic system. Although a command button on your form is an object,
the command button is not a system object because the object did not really exist
(only its pattern existed on the Toolbox window) before you placed the command button
on the form.
Table 22.1 lists all the predefined system objects your applications can work
with.
Table 22.1. The system objects and their methods.
| Object |
Description |
Methods |
| App |
Your current application |
The method called EXEName returns the application's filename. Path
returns the application's path. Title returns the primary startup form's
title bar text. Previnstance returns True or False to
indicate whether another instance (copy) of the application is currently running. |
| ClipBoard |
The Windows Clipboard |
The method Clear erases the Clipboard. GetData returns the graphic
image stored on the Clipboard. GetFormat returns the format of the Clipboard
object. GetText returns the text on the Clipboard. SetData copies
a graphic image to the Clipboard. SetText copies text to the Clipboard.
SelStart, SelLength, and SelText perform the Clipboard's
selection operations. |
| Debug |
The Immediate window |
The method Print copies information, at runtime, to the Immediate window
(only possible in non-.EXE Visual Basic programs you run from Visual Basic's
development environment). |
| Printer |
The system printer |
Provides printer support. |
| Screen |
The user's screen |
FontCount returns the number of fonts the current screen supports. Fonts
contains a list of all of the screen's possible font names. Height returns
the twip height of the screen area. MousePointer holds (or determines if
you specify a new one) the shape of the mouse cursor. TwipsPerPixelX returns
the number of possible horizontal twips. TwipsPerPixelY returns the number
of possible vertical twips. Width returns the width, in twips, of the screen. |
Use these objects and methods to return information about the objects. For example,
you could append the current application pathname to a string variable like this:
strFullName = Application.Path & "Afile.dat"
Although you won't use the system objects in every application, they do come in
handy when you're performing interaction with the Windows Clipboard or the screen.
TIP: The Screen
object's measurements differ depending on the video card, resolution, and monitor
your user uses. Therefore, the Screen object, available at runtime, represents
the entire Windows Desktop. If you want to center a form in the middle of the user's
screen, you could place these statements at the beginning of the Form_Load()
event procedure:
frmName.Left = (Screen.Width - frmName.Width) / 2
frmName.Top = (Screen.Height - frmName.Height) / 2
Program Objects
New Term: A class is a packaged object,
with behaviors and properties, that describes members of the class.
Objects that you create with your application are objects that are members of
a particular class. For example, an option button class defines properties, events,
and methods that all members of the option button class support. In other words,
even though your application may contain five option buttons, and even though all
five of those option buttons differ in one or more of their properties (such as Caption),
they are all members of the same class. A command button can never be a member of
the option button class because a command button's properties, events, and methods
differ from an option button's.
You can test for membership within any given class. The class forms a hierarchy
and all members of the class take on the class properties, events, and methods. One
of the reasons for a class test is that you can pass to procedures not only variables,
but also controls. The following procedure receives a command button as its only
argument:
Public Sub GetIt(cmdClick As CommandButton)
Some procedures can be multipurpose. In other words, a procedure might change
the BackColor property of whatever object you pass to that procedure. Use
the As Object argument declaration as follows to make the procedure multipurpose:
Public Sub ChangeColor(objOnForm As Object)
You've not seen the Object keyword until now, but you can declare not
only arguments as Object data types, but variables as well, like this:
Dim objAnything As Object
The objAnything variable can now represent an object.
Your application's code can create any object needed at runtime. In other words,
you could declare an array of five option buttons like this:
Dim ctlOpButtons(1 To 5) As New OptionButton
The New keyword tells Visual Basic to create five new option buttons.
If you want to base a new object on an existing object, you only need to change the
properties that differ in the new object from the old one. The following statement
declares a new form based on an existing form named frmAcctsPay:
Dim frmNewForm As New frmAcctsPay
Notice that if you place an existing control name after the New statement,
Visual Basic declares a new object based on an existing one. If you use a control's
class name (such as CommandButton, Form, OptionButton,
or Label), Visual Basic declares a new control with all default property
values (except for the Name property, which you set with the Dim
as you declare the control). You the can specify the property values that you want
for your new object.
Use the If TypeOf-Is programming block to test for an object's data type.
The following If generates True if the object stored in objAnything
is a text box:
If TypeOf objAnything Is TextBox Then
In addition to being a keyword command, Visual Basic supports the TypeOf()
function that returns the object type of its argument.
Knowing about an object's class lets Visual Basic accept the following code that
contains a With keyword block:
With lblTitle
.Caption = "Accounts Payable"
.Alignment = vbRightJustify
.Font.Size = 15
.Font.Bold = True
.Left = 25
.Right = 0
.Width = 1000
End With
If you must set more than two or three properties in code, use With,
which tells Visual Basic that all objects without an object qualifier are
label objects. Without the With keyword, you would have to type the object's
name all through the assignments, like this:
lblTitle.Caption = "Accounts Payable"
lblTitle.Alignment = vbRightJustify
lblTitle.Font.Size = 15
lblTitle.Font.Bold = True
lblTitle.Left = 25
lblTitle.Right = 0
lblTitle.Width = 1000
Using Collections and Object Arrays
In earlier lessons you learned about control arrays that you can declare. By declaring
an array of five Option Button controls, for example, that all have the same name,
you can set property values for one, and all the others gain the same properties.
Your application will distinguish between the controls by the control array subscript.
New Term: A collection is a set of
all objects of the same data type.
In addition to the control arrays, you can work with collections. A collection
differs from an array because your application may contain three command button arrays
but only one Controls collection. The Controls collection refers
to every control used in your application.
Table 22.2 describes common Visual Basic collections.
Table 22.2. Some of the collections you can manage.
| Collection |
Description |
| Controls |
All controls within your application. |
| Forms |
All forms within your application. |
| Printers |
All printers connected to your system. |
The collections support several methods that you can use to manage the collection.
Table 22.3 lists some of those methods.
Table 22.3. Some methods you can apply to collections.
| Method |
Description |
| Add |
Adds items to collections. |
| Count |
Returns the number of items in a collection. |
| Remove |
Deletes items from a collection. |
| Item |
References a collection element. |
NOTE: You can create
your own collections, and some of Table 22.3's methods are more useful to you, when
you work with your own collections than when you work with the supplied collections.
For example, you'd never add an item to the Printers collection because
Windows defines that collection from your system's installed printer list.
Suppose that you want to display all controls on the form, even some that might
be hidden from other procedures that executed previously. Although you could set
each control's Visible property to True, the following loop makes
for an easier display of the controls:
For intCtr = 0 to Controls.Count-1
Controls(intCtr).Visible = True
Next intCtr
The For Each statement makes the loop even simpler. The zero-based collection
subscript requires that you loop through the Count-1 subscript, which is
a little confusing. Substitute For Each to clarify things and to let Visual
Basic take care of the subscripting like this:
Dim ctlControl As Control
For Each ctlControl In Controls
ctlControl.Visible = True
Next ctlControl
Notice that you must declare a control variable so that the For Each
statement has a place to load each control in the collection.
Suppose that you add forms to that same application and you want to make all controls
visible on all the forms. The Forms collection makes such a task simple
if you use the following nested loop:
Dim ctlControl As Control
Dim frmMyForms As Form
For Each frmMyForms In Forms
For Each ctlControl In Controls
ctlControls.Visible = True
Next ctlControl
Next frmMyForms
If you want to create your own collections, you'll be able to work with them just
as you work with the supplied collections. You'll have to declare and manage the
collection yourself, but once you build a collection, you can operate on all the
collection items more easily than if they were separate or part of a control array.
Given that the Collection keyword is itself a defined object, you can
declare a collection like this:
Public colNewCollect As New Collection
If you do not use Dim, but use either Private or Public
to declare collections, declare the collections in the general section of
a module so that the Public or Private keyword determines the scope
(either project- or module-level availability).
WARNING: The previous
Public statement declares a new collection class but does not declare any
specific members of that collection. To use a collection object, you must not define
the specific items to go in the collection.
If you use Dim and declare a new collection inside a procedure, only
that procedure has access to the collection. Often, such a local collection is wanted,
but be aware that other procedures cannot use the collection.
Once you define the collection in the general section, you then can create
the collection's specific instances. Listing 22.1 declares collection members and
shows you how to use the methods to add and manage the collection.
Listing 22.1. Creating and managing
a collection.
Dim colPeople As New Collection
Dim intCtr As Integer
Dim m As Integer ` MsgBox() return (not used)
colPeople.Add "George"
colPeople.Add "Sandra"
colPeople.Add "William"
colPeople.Add "Sue"
colPeople.Add "Terry"
` Print the collection
For intCtr = 1 to colPeople.Count
m = MsgBox("The next name is "; & colPeople(intCtr) )
Next intCtr
` Add another person if you wish
` As you can see, you don't need to
` concern yourself with running past a
` maximum subscript value as you
` would with arrays.
colPeople.Add "Kay"
` The following should display 6 people
m = MsgBox("There are "; Str(colPeople.Count); & _
" in the collection.").
Here is the output from this code:
The next name is George
The next name is Sandra
The next name is William
The next name is Sue
The next name is Terry
The next name is Kay
There are 6 in the collection.
WARNING: As you
can see, a collection's index value begins at 1, not zero, as is the case for arrays
and control arrays. The mixture of starting subscripts provides yet another reason
for using For Each to step through such items.
The previous discussion shows how you can use the Add method to add new
items to the collection. You don't have to worry about a maximum subscript. The problem,
however, is that with Add's default method format, you cannot add new collection
items except to the end of the collection. In addition, you cannot remove specific
items, except for the final collection item, from the collection with Remove.
New Term: A named argument is an argument
known by its name and not by its specific position without an argument list.
Add supports a named argument called Before that lets you insert
new items into a collection before an existing item. In effect, Visual Basic shifts
all the subsequent items down in the list. If you want to add a new name to the beginning
of the People collection, code the following:
People.Add "Robert", Before:=1
WARNING: Do not
use a regular assignment statement when assigning named argument values, but use
the special := named argument assignment operator.
The collection now looks like this:
Robert
The next name is George
Sandra
William
Sue
Terry
Kay
If you want to remove the third name, you can do so like this:
People.Remove 3 ` Deletes the 3rd item
Introduction to OLE Automation
New Term: OLE automation refers to
the capability of one application to declare and use ActiveX objects that are actually
created by other applications.
As you learned in Hour 21, "Visual Basic and ActiveX," the overall distinction
between OLE and ActiveX is getting blurred. Nevertheless, OLE and ActiveX do work
well together to support OLE automation. Although this section only scratches the
OLE automation surface, you'll probably be surprised at what OLE automation can accomplish.
NOTE: More and more
programmers are calling OLE automation active automation due to ActiveX's impact
on OLE automation.
Suppose that your application needed to create data files for Excel or Word. Using
normal file access routines you learned in Hour 15, "Visual Basic Database Basics,"
makes such file creation extremely tedious and bug-prone. How can you find the data
format required by Word?
With OLE automation your Visual Basic application can actually borrow Excel or
Word and, behind the user's back without ever showing the other application, make
Excel or Word (or any other OLE automation-compatible application) create the data
file for you. When finished, the data file will reside on the disk and no traces
of the other application will be left. Your user will believe your application created
the data file.
WARNING: Your development
computer must have a copy of the OLE automation's application before you can test
your application. Also, your user must have a copy of the OLE automation application.
Without Word, for example, you cannot use OLE automation to create a Word document.
To create a Word data file using OLE automation, you must first create an object
variable that can reference the Word OLE automation application. Declare such an
object variable like this:
Public objWordApp As Object
TIP: Always use a global
variable for OLE automation objects. The variable references a completely different
application outside your application's workspace. Therefore, the variable is truly
global to your application's other variables.
objWordApp is an object variable that represents the entire Word OLE
automation application. The rest of the code will use this application's reference
object variable to perform the data-generation task. Nothing about objWordApp
lets Visual Basic know that the object is the Word application, so the following
statement will link the option button variable to Word:
Set objWordApp = CreateObject("Word.Application.8")
The 8 is a property that uses Office 97's Word instead of earlier versions.
Before Office 97, which technically contains Word version 8, Word used a language
called WordBasic for its automation language. Word 8 uses Visual Basic, which is
sometimes called Visual Basic for Applications.
Notice that this is not a normal assignment statement. The Set keyword
tells Visual Basic not to store a value in objWordApp because the Word application
is not a value that you could put into a variable. Set tells Visual Basic
to reference the Word application. objWordApp works like a link to Word.
Visual Basic will, through OLE automation, transfer functions you apply to objWordApp
to the Word application. The CreateObject() function actually starts Word
(in the background) and prepares the OLE automation link.
WARNING: If Word
is already running, CreateObject() starts another copy of Word. If you want
to use the currently running Word, use GetObject() instead of CreateObject()
to borrow the running copy of Word. You can test to see if Word is already running
like this:
Set objWordApp = GetObject("", "Word.Application.8")
If objWordApp Is Nothing Then ` True if not running
Set objWordApp = CreateObject("Word.Application.8")
End If
The null string at the beginning of GetObject()is necessary. If you want
to open an existing Word document and work on that document inside Visual Basic,
you'll insert the path and filename to that document as the first argument. If you
want to use Word to create a new document, leave the null string for the first argument.
Keep in mind that OLE automation is fairly extensive and that you can, through
your Visual Basic application, make Word do anything you could do at the keyboard
with Word. Therefore, the OLE automation can trigger Word's menus, format text, and
save files. You'll apply methods, most of which match Word's menus, to perform these
tasks.
Listing 22.2 shows you a complete code set you could use to create a Word document
named MyWord.Doc.
Listing 22.2. OLE automation code
that uses Word to create a Word document.
` Create a Word document and add text to it
Set objWordApp = GetObject("", "Word.Application.8")
If objWordApp Is Nothing Then ` True if not running
Set objWordApp = CreateObject("Word.Application.8")
End If
` Add a document to the collection
objWordApp.Documents.Add
` The title will have a blank line after it
` Move the cursor to the next line (simulate the
` user pressing Enter) by sending the vbCrLf named
` literal to the document
objWordApp.Documents(1).Content.Font.Size = 28
objWordApp.Documents(1).Content.Font.Bold = True
objWordApp.Documents(1).Content.InsertAfter _
Text:="Why go to Italy?" & vbCrLf & vbCrLf
` The body of the document is next
objWordApp.Documents(1).Range.InsertAfter Text:= _
"Italy sells the best ice cream in the world." & vbCrLf
objWordApp.Documents(1).Range.InsertAfter Text:= _
"Italy has the best architecture in the world." & vbCrLf
objWordApp.Documents(1).Range.InsertAfter Text:= _
"(Oh, and did I mention the ice cream?)"
`Save the document
objWordApp.Documents(1).SaveAs "c:\MyWord.Doc"
` Close the Word document
objWordApp.Documents(1).Close
` Quit the Word application
objWordApp.Quit
WARNING: Listing
22.2 contains a lot of strange-looking properties, events, and methods such as InsertAfter
and Range. These are Word-based Visual Basic objects and properties, events,
and methods. Although you've not seen most of these properties, events, and methods
before, you can probably make a good guess as to what each statement does. (No range
is set up by the code, so Range refers to the cursor's current position
in the document.)
After running Listing 22.2 (perhaps from an event procedure you tie to a command
button), you can open Word and load the MyWord.Doc document created from
Listing 22.2. You'll see that the document is fully Word compatible; it should be
because Word created it from your application's OLE automation commands. Figure 22.1
shows a Word screen with the document open.
Figure
22.1. The Word document that Visual Basic
created with OLE automation.
NOTE: You must be
intimately familiar with the OLE automation application before you can work with
that application through Visual Basic objects. Often the other application offers
online OLE automation support information so you can use that application in an OLE
automation setting. You can get help with Word's OLE automation language by starting
Visual Basic for Applications from Word's Tools menu and viewing the help files there.
Summary
You now understand more about objects and how to access objects from within Visual
Basic. In programming terms, an object is a packaged set of properties and code,
and that's exactly what Visual Basic objects such as controls are. You set a control's
properties and run methods to manipulate those objects. The object model gives you
the ability to pass controls and other objects, test an object's type, and create
your own collections that often make programming easier than arrays.
The next hour explains how to prepare your application for distribution now that
you've learned how to write powerful applications.
Q&A
- Q Why are collections better than arrays?
A Collections are not better than arrays in all cases. For example, if you need
to keep track of 100 integer temperature values, keep those values in an integer
array. The array is efficient and you can work with the array using loops as you
are used to doing. A collection is nice when you don't know how many items will appear
in the group, especially when those items are objects such as controls and not simply
regular data types. The collection can grow to any size and the methods you use on
the collection make for simple programming because you don't have to keep track of
the highest item in the collection yourself.
Q What is the real difference between OLE and OLE automation?
A OLE lets users edit objects from other applications inside a Form window. The
cross-application platforms that OLE provides lets you embed a Paint object
in your application without having to code drawing methods that perform as Paint's
perform. Before OLE automation, however, regular OLE did not give your Visual Basic
application the capability to control the serving application. Applications that
support OLE automation can now expose all their internal properties, events, and
methods (if they're not OLE automation compatible, they will have no properties,
events, or methods) to applications such as Visual Basic. Visual Basic, therefore,
can make Access manipulate database tables or make Excel manipulate a named range
in a worksheet. Although you must do some extra work on the front end to code the
OLE automation, your applications become much more powerful because they borrow technology
from these other applications.
Workshop
The quiz questions and exercises are provided for your further understanding.
See Appendix C, "Answers," for answers.
Quiz
- 1. What are three system objects?
2. What is the difference between a class and an object?
3. What happens when you use the New keyword inside an object declaration?
4. True or false: TypeOf is both a statement and a function.
5. True or false: You can pass objects such as controls and forms as arguments
to procedures.
6. What is the index value for a collection's first item?
7. How can you insert a new item at the beginning of a collection?
8. Which OLE automation function should you use to initiate OLE automation when
the OLE automation application is already running on the machine?
9. What is the new term being used more frequently for OLE automation?
10. True or false: As long as you know the OLE automation language, you don't
need the OLE automation application installed on your machine to use OLE automation
with that application.
Exercises
- 1. Write a procedure that decreases the font size of all controls on all
forms by 50%. Use a system object to accomplish the change.
2. If you use Word, Excel, or any other OLE automation-compatible application
(as all the Office 97 products are), start that application and search the online
help for information on that application's properties, events, and methods used in
OLE automation. The more you know about that application's internals, the more easily
you can integrate that application and borrow its power for your own applications.
If the application is an Office 97 application, search the online help for the Visual
Basic help to see how to start Visual Basic. (Visual Basic is often called Visual
Basic for Applications in applications' help files. Visual Basic for Applications
[or VBA] is the same language as Visual Basic.) Start the application's Visual Basic
editor to see a development environment that looks like Visual Basic's own development
environment. Open the application's Object Browser to receive an Explorer-like view
of that application's properties, events, and methods. Search the Object Browser's
online help for extensive OLE automation help.
 
|