Previous Page TOC Next Page


16 — OLE for the First Time

by Richard Buhrer

OLE, pronounced Olé! (like at a fiesta), and an acronym for "Object Linking and Embedding," is a standard that provides several ways for software programs to communicate with each other. Visual Basic 4.0 has fully implemented OLE 2.x and this has expanded the collection of tools available in the product. A working understanding of objects and OLE 2.x is required in order to get the greatest value from the changes in VB 4.0.

Microsoft's position is that OLE 2.x is not just object linking and embedding anymore. The second (and current version) of the standard has expanded the focus of OLE to include a standard for interapplication communication. One good way to summarize the differences between OLE 1.0 and OLE 2.x, is that 1.0 was about object linking and embedding, whereas OLE 2.0 is about objects, and linking and embedding are only one part of the picture.

Navigating This Chapter

This chapter begins with a discussion of the object linking and embedding technology. If you already have a basic understanding of OLE 2.x technology, then you might skip or skim the first section as a review. The following section discusses Visual Basic's place in the world of OLE 2.x. The third section explores Visual Basic 4.0's place as an object oriented programming language. It discusses ways to implement object oriented design techniques providing VB programmers with reusable code and bulletproof applications. The final section presents some resources for further information on object linking and embedding.

An Introduction to Objects, Linking, and Embedding

"Object" is one of the most abstract and amorphous words in the English language. Just about any entity we can talk about qualifies as an object. Webster's Dictionary defines an object in this way:

(1)

ob.ject)(n)(14c)<objectum, >fr. L, neut. of ><obicere >to throw in the way, present, hinder, fr. ><ob-> in the way + ><jacere >to throw

1a:

something material that may be perceived by the senses <I see an object in the distance.>

1b:

something that when viewed stirs a particular emotion (as pity) <look to the tragic loading of this bed ... the object poisons sight; let it be hid —Shak.>

2:

something mental or physical toward which thought, feeling, or action is directed <an object for study> <the object of my affection> <delicately carved art objects>

3:

the goal or end of an effort or activity: PURPOSE, OBJECTIVE <their object is to investigate the matter thoroughly>

4:

a thing that forms an element of or constitutes the subject matter of an investigation or science

5a:

a noun or noun equivalent (as a pronoun, gerund, or clause) denoting the goal or result of the action of a verb

5b:

a noun or noun equivalent in a prepositional phrase

What Is an Object, Anyway?

The software industry has developed several meanings of the term, "object." Marketing types have appropriated the word and turned "object-oriented" into a buzzword. Almost every major piece of software claims to be object oriented. To restore some clarity, here are some of the relevant definitions of objects:

Object-oriented software theorists understand an object to be a component of a software program that "models" or "represents" a something in the real world, like a ledger or a bicycle. Because of this correlation between real world and software objects, it is allegedly easier to construct re-usable software components and to reduce bugs by isolating one module of a program from changes in another. In order to qualify as an object, the design must support four qualities:

Devout OOP programmers vehemently argue whether OLE 2.x "objects" deserve the name. It's something of an irony that theorists would choose one of the most vague words in the English language and then get huffy about the imprecise use of the term. We'll explore the details of this is the third section of this chapter.

From Visual Basic's perspective, objects are combinations of code and data that function as a unit. In another sense, an object is a user interface element in Windows (or any other operating system), for example, a program window, a text box, a command button, and so on.

Finally in the pure sense of object linking and embedding, an object is a self-contained bit of information that lives in a compound document. It behaves the same regardless of the application that manages the compound document because the object determines its own behavior. Such an object has two levels of data: presentation data and native data. Presentation data allows the object to be viewed on screen or in print. Native data is the binary information stored in random access memory or on disk and underlies the presentation. In linking, the native data resides on the user's disk in a separate file or document; in embedding, the native data resides in the compound document itself.

A Short History of OLE

It is helpful to review the history of object linking and embedding, which may help clarify the muddle. This "history" might be subtitled "The Quest for Integration," because it is driven by the need to provide the end-user with tools to assemble data in different formats into cohesive presentations or documents. To make this more vivid, let's take the example of Joe User who has the following task to perform: He needs to analyze sales performance for four divisions of the company, and send this analysis along with a cover letter to all sales personnel in the company.

"The Dark Ages"

Back before the birth of graphical user interfaces, we were stuck with applications that couldn't communicate with each other.

Joe uses a flat file database, a character mode spreadsheet and a character mode word processor. To accomplish this task he opens the database program and exports a tab delimited text file containing the list of sales personnel and their addresses. Then he closes the database. He opens a spreadsheet program and creates a spreadsheet in which he constructs a summary table of sales information based on other spreadsheets. This, in itself, could get pretty tedious because the spreadsheet may not support multiple open files. He prints copies of the spreadsheet, closes the spreadsheet program, and then he opens the word processor. He types a mail merge letter laboriously, and retypes the spreadsheet information into the word processor as a table (with tab characters separating the report columns). He prints the letter several times to get the formatting and alignment just right, then he runs the mail merge. Finally, he stuffs envelopes, feeds them through a postage meter, and sends them on their way. Yes, it's easier than doing it with a ledger and a typewriter, but....

Cut, Copy, Paste

Along comes Windows, or Desqview, or a Macintosh, and Joe's work gets a little easier; he can switch between running applications and he can use a clipboard. He still needs to save the database information in a format his word processor can understand, but he can copy parts of the spreadsheet directly into his document. However, it needs to be reformatted to look good, and if the data in the spreadsheet changes, he has to repeat this process. It is very easy for errors to slip into the process and bosses being the way they are, well....

DDE and Links

Windows 2.1 comes with Dynamic Data Exchange (DDE) and links. Joe's word processor might even be able to read the database tables directly for the mail merge, and using Excel or some other Windows-based spreadsheet he can paste a link into his Word document that always reflects the current state of the spreadsheet data in the document. Unfortunately, DDE is slow. When Joe uses this approach, Windows often crashes mysteriously (remember UAEs, Unforgivable Application Errors), and he can only transfer text, not graphs or pictures.

Object Linking and Embedding (OLE 1.0)

Windows 3.x and OLE 1.0 comes along. Now Joe can either embed or link the spreadsheet data into his document. If he double-clicks on the embedded or linked data, the spreadsheet application launches in a separate window and Joe can edit the data directly. He can use graphs from the spreadsheet, and the data is always up to date, but the system slows to a crawl with multiple applications running, and it seems to take forever when switching between editing applications.

OLE 2.x

OLE 2.x comes along. Now when Joe double-clicks on his spreadsheet data, the toolbars and menus of the word processor change to those from the spreadsheet. When he clicks outside of the spreadsheet object, they return to the usual ones for the application. If he has both applications running, he can actually drag a selection from one application into another with his mouse. Although it feels like developing a single document in a single application, he now has the ability to develop compound documents that hold OLE 2.x objects from a variety of sources. Applications that support compound documents can allow him to edit the various components transparently. Additionally, instead of paper mail, he can broadcast these letters across the network as attachments to e-mail messages that can be dispatched directly from the word processor. The applications he uses are large and require a lot of memory, and he has to add more RAM to his machine. Even after adding a substantial amount of RAM, he gets these mysterious out-of-memory messages from Windows when he is really only out of resources. Finally, some of these maneuvers can still be pretty slow on the hardware bought just a year or two ago. Joe is now working on a network and unfortunately some of these nifty features do not work across the network.

Beyond OLE 2.x

Microsoft is promising a standard for distributed OLE so that Joe will be able to use objects across the network from applications that are actually running on other computers. This is yet to be seen.

Through OLE 2.x, computer programs are assisting users to move from a program-centric model of computing to a document-, or data-centric model. In the program-centric model, considerable learning is required to master the foibles of different programs and there are difficulties involved in presenting information in various formats (graphs, pictures, tabular data, formatted text) in the same document or presentation. In the document-centric model (which is yet to be fully realized) a user can transparently assemble information in different formats and present it to others while focusing only on meaning and content. This is a work in progress and the transition is far from complete.

The OLE 2.0 Feature Set

OLE 2.x is a complex technology that has been notoriously difficult for developers to implement. It is constructed on a layered model as shown in Figure 16.1. The upper layer describes the features available for use by (or customization for) the end user. The infrastructure describes the low level services that are managed by the operating system and by Visual Basic. For the most part, the Visual Basic programmer is shielded from these details. The grayed areas of the model are areas of special interest for Visual Basic programmers. Interface in OLE is a means by which two programs communicate with each other: for example, drag and drop, or programmability.


Figure 16.1. The Layered model of OLE 2.x.

OLE 2.x is based on the Component Object Model or COM. You might say that COM acts like a dating service for software components, introducing them and then slipping into the background while they communicate. It continues to work in the background managing the infrastructure services.


NOTE

The System Registry

OLE manages information about programs in a database called the system registry. The registry in 16-bit Windows manages only information about OLE servers: where they are located on disk, what objects they provide, and file extension information that enables File Manager to manage drag and drop. In 32-bit Windows, the registry takes over many other functions including that of initialization files (*.INI).

The registration database is contained in the REG.DAT file found in the \Windows\System directory in Windows 3.x and Windows 95 and in the \Windows\System32 directory in Windows NT. There is an application called REGEDIT which allows users and developers to browse (and at their own risk, edit) the system registry. If you browse the system registry you will find it has a tree structure similar to an MS DOS directory tree. There are root entries with subentries with further sub-entries and finally, values. Entries and sub-entries would be analogous to directories or folders and values to files.

Visual Basic 4.0 provides four new statements for initialization file and registry information management. These are GetSetting, SaveSetting, DeleteSetting, and GetAllSettings. These functions manage initialization file entries on 16-bit Windows and registry information on 32-bit Windows. The good news is that you won't need to use API calls anymore to manage this information. It's finally native to Visual Basic.

You can find more information on this from the Visual Basic help file system or in Chapter 17 of the Programmers Guide, "Interacting with the Environment."

From the user's point of view, OLE 2.x provides the following features:

Visual editing or in-place activation is how embedded or linked objects present themselves in an OLE 2.x-aware application. Instead of opening a separate window for editing, the menus and toolbars of the client application change and display the menus and toolbars of the server application.

OLE 2.x compound documents allow for nested objects, so one could place a graphic object on a spreadsheet table inside a word processing document.

Drag and drop allows the use of the mouse to transfer data from one application to another without using the Clipboard. There are three levels of drag and drop functionality in OLE 2.x:

Finally, and probably most importantly to VB programmers, OLE 2.x Automation allows objects to expose a programmable interface to OLE 2.x-aware programming and macro languages. This allows programmers to develop integrated solutions that utilize features of several applications to automate tasks for end-users.


CAUTION

Containers, Controllers, Clients, Servers?

Every few years, the folks at Microsoft change the terminology used to describe these interapplication services. Source/target, client/server, and so forth. Now the terminology has changed again and requires just a bit of clarification. An application that manages compound documents is now called a container application. It was formerly referred to as an OLE client. An application that provides compound document objects (formerly called a server) is now called an object application. You'll notice, of course, that most container applications are also object applications.

In terms of OLE automation, the client application is now called an object controller. The OLE automation server (which is still the legitimate term) is usually referred to simply as an object.

In summary, in the wonderful world of OLE 2.x there are really two types of objects: programmable objects and non-programmable objects. Non-programmable objects are components of compound documents. They reside in the interface between users and documents. Examples of this type of object are sounds, animations, text, spreadsheet tables, and graphics, in other words, "multimedia." Programmable objects, or OLE 2.x Automation objects, reside in the interface between programmers and production software. They allow themselves to be manipulated through properties and methods.

Visual Basic in the World of OLE 2.x

Visual Basic interacts with both programmable and non-programmable OLE 2.x objects. Table 16.1 describes the implementation of OLE services in Visual Basic 4.0. It includes only those services that are native to Visual Basic 4.0. Other support may be available in add-ins and third party custom controls.

OLE 2.x service


Visual Basic Support


Visual Editing

Visual Basic forms in conjunction with the OLE container control support visual editing with toolbar and menu negotiation, that is, they allow the menus and toolbars of a Visual Basic application to update with information from server applications.

Compound documents

You can display compound documents in a Visual Basic form or in an OLE 2.x container control, previously called the OLE custom control in Visual Basic 3.0; however, you may not create a server application that provides OLE 2.x non-programmable objects similar to Visio drawings or Word documents.

Non-programmable objects

These can be embedded or linked to Visual Basic forms and OLE container controls.

Drag and Drop

The OLE container control can function as the target for an interapplication drag and drop maneuver.

OLE Automation

Fully supported as both a controller and as an object itself.

Visual Basic Non-Programmable Objects

Right off the bat, it's important to point out what Visual Basic cannot do: it cannot create an application that manages compound documents and provides objects to fill them. You cannot write a Visio, Microsoft WordArt, or the answer to Excel in Visual Basic, but there is interesting new support for non-programmable OLE objects in Visual Basic.

Insertable Objects

Visual Basic forms can function as OLE containers without using the OLE 2.x control. One can place objects like graphs, drawings, and sounds directly on forms. The objects will even show up in the Toolbox window, and you can draw them directly on the form in the same way that you draw controls (see Figure 16.2).


Figure 16.2. Tools for Excel and Word are displayed in the Visual Basic 4.0 Toolbox window.

In this way, a programmer can produce an interface that uses elements from various applications for an integrated presentation on-screen, for example, in EIS (Executive Information Systems) applications (see Figure 16.3). There are several examples of this type of program in the Microsoft Office Developers Kit which is included with the Professional Edition of Visual Basic 4.0.


Figure 16.3. An EIS application from the Office Developers Kit.

Although this application, developed in Visual Basic 3.0, uses OLE custom controls to contain the various elements, Visual Basic 4.0 supports drawing them directly on forms.

The OLE 2.x Container Control

Even though there is direct support for insertable objects on Visual Basic forms, there are additional advantages to be gained by using the OLE control.

Example: A Trivial OLE 2.x Browser

This application consists of a single form with six controls. The controls are:

Figure 16.4 shows the Viewer project in the development environment.


Figure 16.4. The OLE Viewer form in the development environment.

There is one menu with two submenus. Figure 16.5 shows the Menu Design window with the menus for the OLE Viewer.


Figure 16.5. The Menu Design window.


Figure 16.6. The OLE Viewer application running.

Following is the code for the entire application. Figure 16.6 shows the application running.

VERSION 4.00

Begin VB.Form Form1

   Caption         =   "Form1"

   ClientHeight    =   4935

   ClientLeft      =   1410

   ClientTop       =   1815

   ClientWidth     =   6060

   Height          =   5625

   Left            =   1350

   LinkTopic       =   "Form1"

   ScaleHeight     =   4935

   ScaleWidth      =   6060

   Top             =   1185

   WhatsThisButton =   -1  'True

   WhatsThisHelp   =   -1  'True

   Width           =   6180

   Begin VB.ListBox List1

      Height          =   840

      Index           =   2

      Left            =   4020

      TabIndex        =   4

      Top             =   660

      Width           =   1815

   End

   Begin VB.ListBox List1

      Height          =   840

      Index           =   1

      Left            =   2100

      TabIndex        =   3

      Top             =   660

      Width           =   1815

   End

   Begin VB.ListBox List1

      Height          =   840

      Index           =   0

      Left            =   180

      TabIndex        =   2

      Top             =   660

      Width           =   1815

   End

   Begin VB.Label Label1

      AutoSize        =   -1  'True

      Caption         =   "Object Get Formats"

      Height          =   195

      Index           =   2

      Left            =   4020

      TabIndex        =   8

      Top             =   420

      Width           =   1365

   End

   Begin VB.Label Label1

      AutoSize        =   -1  'True

      Caption         =   "Object Accept Formats"

      Height          =   195

      Index           =   1

      Left            =   2100

      TabIndex        =   7

      Top             =   420

      Width           =   1620

   End

   Begin VB.Label Label1

      Caption         =   "Object Verbs"

      Height          =   195

      Index           =   0

      Left            =   180

      TabIndex        =   6

      Top             =   420

      Width           =   1035

   End

   Begin ComctlLib.StatusBar StatusBar1

      Align           =   2  'Align Bottom

      Height          =   255

      Left            =   0

      Negotiate       =   -1  'True

      TabIndex        =   5

      Top             =   4680

      Width           =   6060

      _Version        =   65536

      _ExtentX        =   10689

      _ExtentY        =   450

      _StockProps     =   68

      AlignSet        =   -1  'True

      SimpleText      =   ""

      _timers         =   2

      NumPanels       =   3

      i1              =   "Form1.frx":0000

      i2              =   "Form1.frx":010C

      i3              =   "Form1.frx":01FB

   End

   Begin ComctlLib.Toolbar Toolbar1

      Align           =   1  'Align Top

      Height          =   390

      Left            =   0

      Negotiate       =   -1  'True

      TabIndex        =   1

      Top             =   0

      Width           =   6060

      _Version        =   65536

      _ExtentX        =   10689

      _ExtentY        =   688

      _StockProps     =   100

      ImageList       =   ""

      NumButtons      =   2

      i1              =   "Form1.frx":02EA

      i2              =   "Form1.frx":046A

      AlignSet        =   -1  'True

   End

   Begin VB.OLE OLE1

      Height          =   2895

      Left            =   180

      TabIndex        =   0

      Top             =   1620

      Width           =   5655

   End

   Begin VB.Menu mnuFile

      Caption         =   "&File"

      NegotiatePosition=   1  'Left

      Begin VB.Menu mnuFileNewObject

         Caption         =   "&New Object"

      End

      Begin VB.Menu mnuFileSep1

         Caption         =   "-"

      End

      Begin VB.Menu mnuFileExit

         Caption         =   "E&xit"

      End

   End

End

Attribute VB_Name = "Form1"

Attribute VB_Creatable = False

Attribute VB_Exposed = False

Option Explicit

Private Sub mnuFileExit_Click()

    Unload Me

End Sub

Private Sub mnuFileNewObject_Click()

    Dim I   ' Declare counter variable.

    Dim Buffer As String 'for string manipulation

    'Clear the OLE Control if it contains an object

    If OLE1.Class <> "" Then

        OLE1.Close

    End If

    ' Display the Insert Object dialog box.

    On Error GoTo ThisWayOut

    OLE1.InsertObjDlg

    On Error GoTo 0

    ' Update the list of available verbs.

    Buffer = OLE1.Class

    Me.Caption = "This is not " & _

        Left$(Buffer, InStr(Buffer, ".") - 1) & _

        " running."

    OLE1.FetchVerbs ' Fetch verbs.

    ' Clear the list boxes.

    For I = 0 To 2

        List1(I).Clear

    Next

    ' Fill the verbs list box. Because ObjectVerbs(0) is

    ' the default verb and is repeated in the ObjectVerbs()

    ' array, start the count at 1.

    For I = 1 To OLE1.ObjectVerbsCount - 1

        List1(0).AddItem OLE1.ObjectVerbs(I)

    Next I

    'Fill the Accept Formats list box.

    For I = 0 To OLE1.ObjectAcceptFormatsCount - 1

        List1(1).AddItem OLE1.ObjectAcceptFormats(I)

    Next I

    ' Fill the Get Formats list box.

    For I = 0 To OLE1.ObjectGetFormatsCount - 1

        List1(2).AddItem OLE1.ObjectGetFormats(I)

    Next I

    Exit Sub

ThisWayOut:

    OLE1.Class = ""

End Sub

Visual Basic and Programmable Objects

I know that this borders on gushing, but OLE Automation is a magic kingdom for Visual Basic programmers. The syntax of OLE Automation is already well understood by anyone with even a passing understanding of Visual Basic. The level of integration and customization of off-the-shelf and original Visual Basic software should provide Visual Basic users with fine economic opportunities for a long time to come.

In order to appreciate the wide range of new tools in Visual Basic 4.0, this section starts with a brief discussion of some of the underlying technology of OLE Automation, and a third-party tool that is very useful for exploring the capabilities of OLE Automation servers. Then the section steps through the relevant features in Visual Basic 4.0. These include:

You use a rudimentary Visual Basic application, improving it at the various stages to illustrate the uses more concretely.

Type Libraries and a Better Mousetrap

When an OLE Automation server is installed on a system, it must be registered in the system registry with information about the location of the server application or DLL and information about the objects it provides. When it is installed, the application generates a file with a distinctive extension (*.tlb, *.olb, and *.ola are usual extensions). This file contains information about the programmable object the application exposes, including constants, properties, events (in the case of OLE controls), and methods. These are defined in object definition language and compiled in a binary form that is not humanly readable.

In order to use the programmable objects, a programmer needs either documentation from the publisher of the software or a utility that displays the contents of the type library in an understandable format. Visual Basic for Applications and Visual Basic 4.0 contain a built-in Object Browser dialog that does this in a rudimentary way (see Figure 16.7). The first version of the Microsoft Developers Kit contained a free-standing version of the dialog as well.


Figure 16.7. The Object Browser in Visual Basic 4.0.

There are problems with the native Object Browser dialog, though. It lists all the properties, methods, and events for a particular object in a single list box in alphabetical order without any instruction about which item is a property or method or whatever. You have the option of pasting from the dialog to your development environment but only as a declaration, for example "Const xlBar = 2". Although this is helpful as far as it goes, there is now a better alternative.

Apex Software has released a product called VBA Companion. This is the better mousetrap: a full-feature object browser. In addition to the services of the native object browser, VBA Companion separates properties, methods, and events into separate lists but also provides immediate access to the full range of details (see Figure 16.8). Whereas the native browser only allows you to add comments to your own objects, VBA Companion allows you to add notes or annotations to the type libraries on your system to help you with future use of the objects.


Figure 16.8. VBA Companion.

In addition to the clearer exposition of the contents of type libraries, VBA Companion allows you to paste information into your programs as comments, declarations, or statement/function templates. For example, VBA Companion copies this to the clipboard when you use the context menu:

xlBar

But when you select it and use the Edit menu's Copy command, it copies the declaration

Const xlBar = 2

Similarly, for a function or sub, when you use the context menu it copies the template for a function or statement (this example uses a method of the Arc object in Excel 5.0).

arc.CopyPicture(Appearance:=, Format:=)

When you use the edit menu it copies the declaration and adds the End Function line, a feature that Visual Basic supplies automatically but Visual Basic for Applications does not.

Function CopyPicture (Appearance As Variant, Format As Variant) As Variant

End Function

These features can be very helpful when one is struggling with object hierarchies from other applications.

Example: A "Run..." Dialog Box

To illustrate the range of OLE Automation services in Visual Basic, I have chosen the Run dialog. Frequently found in shell replacements and utilities for Windows, the Run dialog allows a user to enter a command line to be executed by Windows. Figure 16.9 shows the Run dialog from Windows 95.


Figure 16.9. The Run dialog from Windows 95.

You'll step this simple dialog through the various layers of OLE Automation support in Visual Basic 4.0. The form that functions as the run dialog has an image control with an icon in it, a text box, three command buttons, and a common dialog control. Figure 16.10 shows the form for our Run dialog in the Visual Basic development environment.


Figure 16.10. The form for our Run dialog.

Forms as Objects

In Visual Basic 4.0, forms are fully qualified OLE objects. This means that, in addition to the event procedures and built-in properties, one can declare public variables and public functions that then function as custom methods and properties for the form. In our example there is one private and one public variable declared at the Form level.

Option Explicit

Public CommandLine As String

Private boolOK As Boolean

There are two public functions declared at the form level; the first displays the dialog and the second executes the command line that the user has chosen in the dialog.

Public Function Display() As Boolean

    Me.Show vbModal

    Display = boolOK

End Function

Public Function Execute() As Variant

    Dim lngResult As Long

    'This will return a variant of type error

    'if the command line does not execute successfully

    'Otherwise it returns the task ID as a variant

    'to the calling procedure.

    On Error Resume Next

    lngResult = Shell(CommandLine, vbNormalFocus)

    If Err.Number <> 0 Then

        Execute = CVErr(Err.Number)

    Else

        Execute = lngResult

    End If

End Function

The project contains a scaffold form with one command button on it to test the execution of the Run dialog. A scaffold form or program is software whose only reason for existing is to test modules in isolation from each other. The code in the scaffold form demonstrates the syntax to use in addressing forms as objects.

Private Sub cmdRun_Click()

    Dim dlg As New dlgRun

    Dim success As Variant

    success = dlg.Display()

    MsgBox success

    If success Then

        MsgBox dlg.CommandLine

        success = dlg.Execute

        MsgBox success

    End If

End Sub

A major side-effect of this implementation is that forms now support most of the module features in previous versions of Visual Basic. For example, variables declared as public are visible from other modules and forms by using the object.property syntax. Forms now support public or private Declare and Const statements. One can now design sophisticated Visual Basic applications that only contain forms.


NOTE

Collections

You can now develop user-defined collection objects like the Forms or Controls collections in Visual Basic.

A collection is like an array in that it contains a series of similar items. It has advantages over arrays however.

1. Collections have more flexible indexing than arrays. You can use two syntactical forms to address a member of a collection:

Collection(index)—The numerical index that underlies the native order of members in the collection.

Collection!Key or Collection("Key")—The key is a variant element in the member that constitutes the user-identified indexing system.

2. Collections may use less memory than arrays, especially sparse arrays.

3. Collections automatically provide methods and properties for ascertaining the count and adding or deleting elements from the collection.

4. Collections automatically manage memory allocation so you do not need to use Redim or Redim Preserve to dimension the array.

Rounding Out the Dialog with Classes

The Run dialog form can be added to any project and bring full functionality with it. With a simple dialog this would probably be adequate, but Visual Basic 4.0 goes further. In addition to greater functionality in forms, it adds the possibility for developing a new kind of module, called a class module, which is, simply put, a fully functional OLE Automation object. You'll change your form into a fully functional OLE Automation server by adding a class module (*.CLS) to the project.

Instead of accessing the methods of the dlgRun form directly, you'll make the form a private element in the RunClass and only access it through methods of the RunClass.

The following is the text of the class module, RunClass.cls:

Option Explicit

Private dlg As New dlgRun

Public Property Get CommandLine() As Variant

    CommandLine = dlg.CommandLine

End Property

Public Function Execute() As Variant

    Dim varHolder As Variant

    varHolder = dlg.Execute

    If VarType(varHolder) = vbError Then

        Execute = False

    Else

        Execute = varHolder

    End If

End Function

Public Function Run() As Variant

    Run = dlg.Display

    If Run Then dlg.UpdateCommandLines

End Function

Private Sub Class_Initialize()

    Load dlg

End Sub

Private Sub Class_Terminate()

    Unload dlg

    Set dlg = Nothing

End Sub

Some notes about the class module: The distinction between Private and Public properties and methods is supremely important. The underlying implementation in private methods and properties (in this case they are mostly contained in the Run dialog form) can be changed as needed, but the interface that is exposed needs to remain consistent. The advantage of a consistent interface is that the program can be changed over time and still work with OLE controllers (also called client applications) without breaking them or itself. It also demonstrates Property and Class procedures (new procedure types in Visual Basic 4.0). The Property procedures are transparent to the calling application as properties. They are addressed with simple assignment calls. Table 16.02 lists the syntax and effect of each type of Property procedure.

Syntax


Effect


MyProperty = NewValue

Triggers the Property Let procedure

Set MyObject = NewObject

Triggers the Property Set procedure

ThisValue = Object.Property

Triggers the Property Get procedure

This type of procedure allows special processing in response to assignment statements. In this example, all that happens is that information from the private form is expressed to other elements of the program. In more complex programs, this ability could be very useful.

The second new type of procedures are Class procedures: Initialize() and Terminate(). These permit special processing when the object is created and destroyed. In object-oriented programming terminology, these would be called the constructor and destructor for an object. In my experience, the Terminate procedure is most important because it allows necessary cleanup, especially when you are using objects inside the object. This cleanup ensures that any memory assignments are freed up when the object exits.

To test this version, you are still using a scaffold application; there are some minor modifications in this version.

VERSION 4.00

Begin VB.Form frmScaffold

   Caption         =   "Form1"

   ClientHeight    =   4140

   ClientLeft      =   1140

   ClientTop       =   1515

   ClientWidth     =   6690

   Height          =   4545

   Left            =   1080

   LinkTopic       =   "Form1"

   ScaleHeight     =   4140

   ScaleWidth      =   6690

   Top             =   1170

   Width           =   6810

   Begin VB.CommandButton cmdUnload

      Caption         =   "Command1"

      Height          =   795

      Left            =   420

      TabIndex        =   1

      Top             =   1680

      Width           =   2055

   End

   Begin VB.CommandButton cmdRun

      Caption         =   "&Run"

      Height          =   735

      Left            =   480

      TabIndex        =   0

      Top             =   660

      Width           =   1875

   End

End

Attribute VB_Name = "frmScaffold"

Attribute VB_Creatable = False

Attribute VB_Exposed = False

Option Explicit

Dim obj As New RunClass

Private Sub cmdRun_Click()

    Dim success As Variant

    success = obj.Run

    MsgBox obj.CommandLine

    success = obj.Execute

End Sub

Private Sub cmdUnload_Click()

    Unload Me

End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)

    Set obj = Nothing

End Sub
Creating OLE Automation Servers with Visual Basic 4.0

Now, simply by replacing the scaffold form with a module and writing a Sub Main procedure, you have an OLE automation server that can be distributed either as an executable or, and this is quite an advance, as a dynamic link library. The ability to create dynamic link libraries in Visual Basic is limited to OLE automation servers. Nonetheless, now Visual Basic programmers can distribute to other programmers components that are written entirely in Visual Basic without exposing code and providing performance superior to compiled executables in Visual Basic.


NOTE

There are three types of OLE Automation servers: in-process, out-of-process, and remote. Remote servers are not available yet; they are expected in "Cairo," the next major version of Windows NT.

Out-of-process servers run a separate executable with their own code and data memory segments. Other applications address them through a process called lightweight remote procedure calls (LRPCs). LRPCs are a little like DDE calls but are more stable and reliable. They do, however, make a hit on speed.

In-process servers run as dynamic link libraries. Each library has its own code segment but stores its data in the data segment of the calling application. There is a significant performance gain because these servers do not have to use the LRPC system for communication.

Visual Basic 4.0 32-bit professional version allows developers to create both in-process and out-of-process servers.

This is the Sub main procedure for our object server.

Attribute VB_Name = "MainModule"

Option Explicit

Sub Main()

    'Check to see if the application has

    'been launched by a curious user

    If App.StartMode = vbSModeStandalone Then

        Dim msg As String, style As Integer

        msg = "This application cannot be run " _

            & "as a stand alone executable. Sorry! " _

            & "Exiting now."

        style = vbOK + vbExclamation

        MsgBox msg, style, "rbRun.exe"

        'End '(the end statement is not supported in DLLs

    End If

End Sub

The message is presented as a courtesy to people who may be browsing executable files. It at least acknowledges their industry but doesn't allow them to get in trouble, or worse, delete the file because it doesn't appear to do anything.

Note that modules (both normal and class) now have properties. The class module properties deserve some explanation. Table 16.3 explains the various properties for class modules.

Property


Values


Comments


Instancing

0—Not Creatable

1—Creatable Single Use

2—Creatable Multi-Use

Not Creatable means you can only create instances of your server in your own project. Single Use means that you can create instances in and outside of your project but each instance requires a separate copy of the server to be run. Multi-Use allows multiple instances to share the same code segment. This the required setting for DLLs.

Name

Visual Basic's internal name for the module.

This must follow Visual Basic variable naming conventions. It is also a property of normal modules.

Public

True

False

When True, your object is visible to and usable by other applications. It is the required setting for objects you publish for use by others.

Finally, after you compile your application, you need to register it on your system as an OLE 2.x server. If you use the Setup Wizard to package your application for distribution, the SETUP.EXE you create registers your application on the target system. You can register it by hand by using the REGSVR??.EXE program that ships with Visual Basic. The ?? stands for 16 or 32 depending on the target system. You run it from the command line with your server's fully qualified path and file as a parameter. The following line is the command to register the example server on your system, presuming you place it with other common DLLs in your system directory:

C:REGSVR32.EXE C:\WINDOWS\SYSTEM\RBRUN.DLL

If you publish your server as an executable file, it registers itself the first time it is run or if you run it with the /REGSERVER switch.

MYAPP.EXE /REGSERVER

This does not launch the application but registers it with the system and exposes its type library. Figure 16.11 shows the type library for the rbRun.DLL exposed in VBA Companion.


Figure 16.11. The type library for rbRun.DLL in VBA Companion.

The capability of creating OLE 2.x servers is probably the most significant feature in Visual Basic 4.0. This gives Visual Basic programmers access to a whole realm of software production that is likely to become very important with the release of OLE 2.x—aware operating systems like Windows 95.

The Development Environment as an OLE Automation Controller: Creating Add-Ins

Visual Basic 4.0 takes this one step further by exposing its own type library and allowing other applications to "drive" it. This means that developers can create add-ins that customize and automate the behavior of Visual Basic's development environment. Examples of this capability ship with Visual Basic. A simple example is the Align program which aligns controls on a form, but the Data Forms Designer example shows sample code for automated form development based on a data table. The Data Manager application also functions as an add-in.

In order to transform your simple Run dialog into an add-in to Visual Basic, you need to open a new project in Visual Basic and set a reference in the Tools References dialog box to the rbRun Run Dialog object (see Figure 16.12).


Figure 16.12. The References dialog box from Visual Basic 4.0.

In addition, you need to add two class modules and a code module to the project. Note that this project has no form modules in it.

The first class module, RunAddIn, contains the code for connecting the add-in application to Visual Basic.

VERSION 1.0 CLASS

BEGIN

  MultiUse = -1  'True

END

Attribute VB_Name = "RunAddIn"

Attribute VB_Creatable = True

Attribute VB_Exposed = True

Option Explicit

'Storage for the instance of VBInstance given to us in ConnectAddIn

Dim ThisInstance As Object

'Storage for the menu and menuline objects created when the add-in adds its own _menu

'and menulines to Visual Basic

Dim RunMenuLine As Object

'Set up an instance of the menu line Clicked() Event Handlers

Dim RunHandler As New DoDoRunRun

'Storage for the cookies that are passed back

'from ConnectEvents

Dim RunConnectCookie As Long

Sub ConnectAddIn(VBInstance As Object)

    Set ThisInstance = VBInstance

    Set RunMenuLine = ThisInstance.AddInMenu.MenuItems.Add("Run...")

    Set RunHandler.VBInstance = VBInstance

    RunConnectCookie = RunMenuLine.ConnectEvents(RunHandler)

End Sub

Sub DisconnectAddIn(Mode As Integer)

    RunMenuLine.DisconnectEvents RunConnectCookie

    ThisInstance.AddInMenu.MenuItems.Remove RunMenuLine

    Set ThisInstance = Nothing

End Sub

Notice that there are module-level object values to hold references to the calling instance of Visual Basic and other variables that represent objects in the Visual Basic environment. The most significant example in this case is the MenuLine object, which represents an entry on the Add-Ins menu in the development environment. The two required procedures that the Visual Basic Add-In Manager uses to install and remove the add-in are in this module. Note that to register an add-in you store a reference to the instance of Visual Basic, create the menu lines you need, set a reference to the Visual Basic instance in the EventHandler modules (in this case, it is the other class module, DoDoRunRun (pardon the whimsy). Finally you use the ConnectEvent method of the MenuLine object to retrieve a "cookie" (actually a long pointer to a function in C or C++). To disconnect, the process is neatly reversed, removing the event connect, deleting the menu entries, and releasing the reference to Visual Basic.

The second class module, DoDoRunRun, manages the operation of the Run dialog.

VERSION 1.0 CLASS

BEGIN

  MultiUse = -1  'True

END

Attribute VB_Name = "DoDoRunRun"

Attribute VB_Creatable = False

Attribute VB_Exposed = True

Option Explicit

Public VBInstance As Object

Private dlg As New RunClass

Public Sub AfterClick()

    dlg.Run

    dlg.Execute

End Sub

The AfterClick() method of this class is required for an add-in. It represents the action taken on the Click event on the menu item. The settings for the Instancing and Public properties of this module are interesting. When a module is Instancing=3, (Creatable Multi-Use) and Public = True, the object is a Creatable OLE 2.x object. That means that it can be instanced with the New keyword in a Set or Dim statement or with the GetObject or CreateObject functions in Visual Basic. When Public = False, then the object is a programmable object, that is, it can be controlled from outside of the module, but it can't be independently instantiated. Using VBA Companion, you see this distinction of creatable versus programmable objects in all of the object hierarchies you browse. This is an important consideration in object design (a topic that needs to be dealt with elsewhere). Figure 16.13 shows the Run item on Visual Basics Tools menu, and Figure 16.14 shows the Run dialog launched.


Figure 16.13. The Run dialog option on the Add-Ins menu.


Figure 16.14. The Run dialog running in the Visual Basic development environment.

Programming Other Application Objects

Programming other application's objects is covered well in any number of references and is not a feature new to this version of Visual Basic. Suffice it to say that Visual Basic continues to be the environment of choice for customization and inter-application coordination when the applications are OLE aware.

Overview of Visual Basics OLE Features

Visual Basic 4.0 offers a range of new OLE features including support for compound document objects in forms and in the OLE container control, menu, toolbar, and status bar negotiation with OLE document objects. For programmers, the more valuable changes are in the support for OLE automation, including the ability to develop OLE automation server application and dynamic link libraries. Visual Basic utilities can now be developed in Visual Basic itself and installed in the development environment. Visual Basic now supports multiple instances so that Visual Basic can be used to debug OLE servers and add-in programs. An entire range of new business opportunities for Visual Basic programmers flows from these features.

Visual Basic and Object Oriented Programming (OOP)

Object Oriented Programming (OOP) requires the implementation of four qualities in a programming language: abstraction, encapsulation, polymorphism, and inheritance. Abstraction is a process of dividing your program into chunks that have a correlation with the real world problems the program is meant to solve. Rather than focusing on the function as the unit of interest, in OOP you focus on the object. This means that you can deal with more of the program at once without straining your mental faculties, so to speak.

Encapsulation is the process of making an application out of a series of black boxes which have predictable input and output, but whose inner functioning is unknown and unknowable.

Polymorphism is a more difficult concept to grasp. The bottom line is that different objects can interact without knowing before runtime what the other objects will be. A good example might be a computer game that supports different rockets. Each of these rockets exposes a trajectory property that varies with the design of the rocket. A screen painting module could interact with these rockets and access their trajectory property to paint them differently on the screen. It need not know beforehand how many of which kinds of rockets there are in order to successfully managing their presentation on screen.

The argument has raged for the life of Visual Basic about whether it qualifies as an object-oriented development tool. In the earlier versions of Visual Basic, the only claim to OOP was the use of controls and forms which had some object-oriented features in that they had both properties (data) and methods (procedures that manipulate the data). Visual Basic added a further dimension to this through the event-driven model. Events represented the interaction between the user and the objects exposed by the programmer, but for any reasonably rigorous definition of OOP, Visual Basic did not begin to qualify.

Inheritance is a process whereby one class of objects inherits all the qualities of a parent class of objects simply by reference, that is by the programmer stating in the object that it is of type X.

Many developers attempted to support OOP principles by separating data and procedures into separate code modules. Version 3.0 supported the use of Private variables and procedures. This allowed more abstraction and encapsulation; however, this was not a feature of the development environment but an innovation by programmers.

With the addition of class modules, more features of OOP are accessible to Visual Basic programmers. Abstraction and encapsulation are easily implemented with these modules. Inheritance is not supported by reference, but with careful planning of objects, one can accomplish a sort of inheritance by containment. For example, a class that managed File I/O and error checking could be included as a private member of a class that managed the file content. The second class inherits the functions of the other class by containment. Granted, this is not accomplished as simply and transparently as it is in C++, but the opportunity is at least seminally present.

Similarly, with careful design, polymorphism is supported in Visual Basic. Object references can be changed transparently, so that the same variable could represent the rocket from Apollo 13 and later represent the rocket of the space shuttle with different values in properties of the same name and with different functionality exposed in methods of the same name. In this way, the details of which object is interacting at which time need not be established until run-time.

The bottom line is that Visual Basic is evolving into an object-oriented language but does not fully embrace all the features of an OOP (at least as it is "religiously" understood). The object-oriented feature of Visual Basic, however, does present new opportunities for better architectural designs and more stable software.

Where to Go Next

OLE and object oriented design are complex topics, and both are having significant influence on the computer industry at this time. Visual Basic offers an array of tools to participate in this revolution. To realize this promise, programmers need a fairly detailed understanding of the processes involved. Visual Basic programmers have the opportunity to exploit these features without enduring the pain of C and C++ (pardon the prejudice). For further information, consider some of the following references:

For more information on OLE 2.x:

For more information on OLE Automation with Microsoft Office:

For in-depth discussion of object-oriented design,

Finally, for overall information on software construction and design:

Previous Page TOC Next Page