Visual Basic Expert Solutions

book coverQUE

Chapter 12

OLE Servers

By Edward B. Toupin


This chapter introduces you to the concepts of OLE from a server application perspective. We first take a look at exactly what an OLE server is, the different types of servers, and how servers fit into the OLE hierarchy. We then examine some of the capabilities of a Visual Basic OLE server and operations that you can perform under Windows.

Once the basics are covered, we will step through the development of a Visual Basic OLE server application, including debugging and application distribution. The application will give you a taste of OLE development from the ground up. Make sure to keep the server that we develop in this chapter because it will be used in the next chapter when we discuss OLE clients and their development.

The following topics will be covered about OLE servers:

What is an OLE Server?

OLE provides a foundation for integration through a set of interfaces. These interfaces are exposed as a set of methods and properties that allow programmatic control of one application by another. Exposing the functionality of applications for access by another makes OLE a very open and extensible technology. The concept of being open means that the functionality of an application may be shared by many applications. OLE extensibility represents the ability to expand the basic functionality of one application by incorporating the functionality of other applications.

OLE servers are those applications which expose their functionality to allow client applications access to the functionality of the server. A server provides a set of services to container applications including embedding, linking, and visual editing.

Types of Servers

Visual editing servers create OLE objects for use by container applications and allow these container applications to incorporate the functionality of the server into the application itself. Visual editing server applications can support both embedded and linked objects but can perform only visual editing on embedded objects because linked objects are file-based. The one common feature of all visual editing server applications is that they all support activation by container applications when you want to edit an object.

A full server is an application that can be run as a standalone application or can be launched by container applications. A full server has the ability to save documents as files on disk when run standalone and can also support linking and embedding when launched by a container. Some full servers can support linking only while others can support embedding only. However, the norm for a full server is to support both methods of object interaction.

A mini server is a server application that can be run only when launched by a container application. A mini server cannot save documents as files on a disk but instead uses the objects stored in the container application from which it was launched. As a result, a mini server can support embedding only, not linking. Examples of mini servers are Microsoft Draw, Microsoft Graph, and Microsoft Equation.

An automation server, also known as an object application, is an application that provides a service other than linking and embedding to other applications. OLE automation provides a means of taking advantage of extensibility of Windows-based applications by allowing the integration of application functionality. Using OLE automation, you can create applications that expose objects and their interfaces to programming tools and macro languages to provide a means of incorporating the server's capabilities into one or more applications. Applications that utilize the capabilities of OLE automation servers are known as controlling applications because they control the functions of the OLE automation servers with which they are communicating.

Note: With regards to linking, embedding, and visual editing, the applications that utilize OLE servers are called containers because they contain objects created by the servers. With OLE automation applications that use OLE automation, servers are called controllers because they control the functions of the automation servers with which they are communicating.

There is a point that is reached during the development of an object application where the requirements of a controlling application exceed the functional capabilities of the object application. In such a situation it is beneficial to move to OLE custom control (OCX) technology.

Windows-based applications take advantage of OLE automation to use code from other applications. Through Visual Basic, you can obtain references to objects in another application and make calls to the application's internal functions as if the code were located in your application. The syntax, type, and number of parameters for each object and function are defined in the application's object library, which provides a detailed map of each of the applications objects.

Visual Basic OLE Servers

Visual Basic allows you to develop object applications that expose their objects for use by many different controlling applications. As you can see in figure 12.1, the controlling application is using the object library for the Visual Basic object application to locate, or map, the methods and properties of the object application. These mapped methods and properties of the object application can be executed by any Windows controlling applications.

Fig. 12.1 Controlling applications use the Type Library to execute methods and use members of Object applications.

Visual Basic OLE Automation Objects

Objects exposed to controlling applications by object applications are known as OLE automation objects. Object applications can expose any number of objects to be used by controlling applications. OLE automation uses what is known as the component object model to allow programmers to manipulate an application's objects from outside that object application.

Component Object Model

The component object model, the result of a consortium for establishing standards as well as the key to OLE's extensible architecture, defines how objects interact with one another, both within an application and between separate applications. The foundation of the model on which the rest of OLE is built provides mechanisms that support multiple interfaces between an object application and controlling applications (see fig. 12.2). The architecture is divided into services supported by the component object model (interface negotiation, memory management, error and status reporting, and task-to-task communications) and other basic services built on the model.

Fig. 12.2 The Component Object Model provides a foundation for communications and data sharing between applications.

The model defines an interface by which a controlling application can communicate with an object application that provides a service for the requesting controlling application. Through the model, each object application can support multiple interfaces to service multiple controlling applications, who may query about support for a specific interface or service.

The model provides a mechanism for task-to-task communications, which provides a means of allowing objects to communicate with controlling applications. This mechanism allows communications to exist across application boundaries so that controlling applications can pass information to the objects of object applications and visa versa.

The model also provides a means of dynamically loading and destroying objects. When an object is requested, the object application in which the requested object exists is loaded or, if the application is already running, the existing object application is accessed.

Each access made by a controlling application increments a reference counter so that the model will know how many interfaces are currently active for an object application. Likewise, as controlling applications release control over an object application, the reference counter is decremented. When all references—and subsequent interfaces—are released, the object application is removed from memory, and that memory is freed by OLE.

Visual Basic Classes

To create objects from a Visual Basic object application, Visual Basic maintains modules known as classes. Each class defines a template for the creation of objects that are used by controlling applications. A Visual Basic class is similar to a data type in that it describes what type of object you are referring to. For example, Visual Basic provides an intrinsic integer data type. In order to use that data type, you have to create a variable of type Integer. With classes, you create a base class (the data type) but before you can use that class you have to create an object (the variable).

Because most of the discussion in this chapter concerns the behavior of the objects you create, the term object is sometimes used in place of class—but do not confuse the two terms. Objects are instances of classes where a Worksheet object is an instance of a Worksheet class. The Worksheet class is the template that is used to create multiple instances of the class as Worksheet objects. Each instance is a usable object accessible by controlling applications.

Visual Basic classes define methods and properties that are exposed to other applications. The methods of the class are used by controlling applications to perform actions on an object while the properties describe the characteristics of an object. When an object of a particular class is created, certain methods and properties become visible to the accessing application. In some cases properties are accessed by procedures known as property procedures. One property procedure might set a particular property's value while the another might retrieve that property's value and return the value to the controlling application.

Designing an Object Hierarchy

An object hierarchy describes the interaction of objects both within an object application and with controlling applications. In object applications that supply more than one object, the application has an object hierarchy. The exposed objects may or may not be related to each other. If they are related, there is often a dependent relationship where the existence of some object cannot exist outside of the context of a higher-level object.

Visual Basic allows you to create object hierarchies in which some objects can be directly created by controlling applications as well as those that cannot. For example, you can set the Creatable property of a Visual Basic class to False if you don't want controlling applications to create a dependent object directly. You can then define a top-level class that includes a method to produce instances of the dependent classes for the controlling applications. This way, all controlling applications must go through the top-level class to reach the dependent objects.

In figure 12.3, Class2 is a higher-level class than Class1. Because Class1 is dependent on Class2 in our hierarchy, you must use the methods of Class2::Object1 or Class2::Object2 to access the methods and properties of objects of Class1. Class3::Object1 and Class3::Object2 are independent objects of Class3 and can be accessed directly by controlling applications.

Fig. 12.3 Classes and their objects are arranged into object hierarchies.

As with Class2 and Class3 of figure 12.3, a Visual Basic class whose Instancing property is set to Creatable MultiUse or Creatable SingleUse and Public property is set to True defines an externally creatable object. Such creatable objects are higher-level objects that can be used to navigate to and use the methods and properties of dependent objects. You can make these creatable objects externally using CreateObject() from a controlling application to directly create an instance (object) of the class from outside the application.

Note: OLE objects defined in an OLE automation object hierarchy are actually OLE classes. The best way to remember the difference is that an object is an instance of a class.

To organize your objects into a hierarchy, you need to define in each higher-level object a method that returns a reference to dependent objects. For example, the externally creatable object Plane defines an AddPassenger() method. The Passenger class, dimensioned as X, is dependent on the Plane class, as shown in Listing 12.1.

Listing 12.1 Accessing Dependent Objects Through Independent Object Methods

Public Function AddPassenger As Passenger (NumOfBags as Integer)
Dim X As New Passenger
X.Bags = NumOfBags
Me.Passenger = X
AddPassenger = X
End Function

In the preceding code, X is defined as an object of the Passenger class. The New keyword allows you to dynamically create an object of an OLE class of the local application in a Dim statement. Once the object is instantiated, you have access to the methods and properties of the object. In this instance you are gaining access to the methods and properties of the Passenger class.

A controlling application cannot obtain a reference to a Passenger object because the object, in this example, is not creatable and is a dependent object of Plane. However, a controlling application can use the Passenger object indirectly by first accessing the Plane object from an application named Ticketing and then using the new object referenced by DC10 to access its AddPassenger method.

DC10 = CreateObject("Ticketing.Plane")
DC10.AddPassenger(2)

Creating an OLE Server in Visual Basic

In addition to the requirements for Windows-based application development in Visual Basic, OLE automation requires a few additional things of a server. As you can see in figure 12.4, you must execute a logical sequence of actions to create an object application in Visual Basic.

Fig. 12.4 To create an object application, several sequential steps must be taken for proper implementation.

The process is simple and parallels some of the things you already know about Visual Basic programming. When it comes to running and using your application, however, the code will be shared with other applications, and the project will take on a different look and feel.

It is essential that you plan your application's object model, or hierarchy. If you do not have a properly planned hierarchy, your application may not be easy to use by controlling applications and may not fit into the standards established for object application interfacing. We will be discussing some of these standards later in the section "Standards and Guidelines."

First determine which classes you will need for your application. Each object in your hierarchy will correspond to one Visual Basic class with all properties and methods for each object defined in a class module. Determine the visibility of your objects—will they be creatable by a controlling application or will they be dependent upon another internal class of the object application. For each class, determine the properties and methods to be used within the instantiated objects of your classes.

As you can see in figure 12.5, we have two independent classes—Picture and Calc. The Picture class has methods and properties to display a picture on a Visual Basic form when commanded by a controlling application. The Calc class contains methods and properties to perform some minor calculations and storage of values.

Fig. 12.5 The base classes contain members and methods that are inherited by derived classes and are used by instantiated objects of the classes.

Note: To create a new project, choose File, New from the Visual Basic menu. Visual Basic will clear its working area and display an empty form to allow you to begin work on the new project.

Adding Classes

You must add one class module for each class that you defined in your object hierarchy. To create a new class, choose Insert, Class Module from the Visual Basic menu. Each new class module that you add will be the template of each object created and used by controlling applications. In these class modules you will add the methods and properties you defined in the classes of your hierarchy.

For this object application you will want to create two classes—one for Calc and the other for Picture. As in figure 12.6, you set the Name property for one class module to Calc and the other to Picture in the property list for the respective module. Controlling applications use the Name property to create object variables that reference the class. In the following example, an application is creating an object variable, X, that uses the Calc class of the AutoSrvr object application:

Set X = CreateObject("AutoSrvr.Calc")

Fig. 12.6 The properties of classes provide a means of establishing the operational characteristics of a class.

Class Public Property

In our object hierarchy, both classes are independent classes and should be made accessible to all controlling applications. Referring back to figure 12.6, you will want to set the Public property for the Picture and Calc class modules to True so that objects of either class can be used by controlling applications.

All classes whose Public property is set to True are registered in the system registry to make them visible to all applications who may request access to the object application's classes. If set to False, the class is available within the project only, and any instances of that class are not visible nor are they accessible outside of the object application.

Class Creatable Property

To allow controlling applications access to the objects of classes, we must set the Public property to True. We want to allow controlling applications to be able to create objects of the two classes using CreateObject(). Referring back to figure 12.6, you will want to set the Instancing property for the Picture and Calc class modules to either Creatable SingleUse or Creatable MultiUse. Creatable SingleUse allows a controlling application to create a single object of the class. Creatable MultiUse allows a controlling application to create multiple instances of a given class.

Note: Classes defined in a class module are always accessible and creatable within your project, even if the class properties of your project are set to False. Setting the Instancing property to any of the mentioned settings except for Not Creatable allows controlling applications access to your classes.

Defining Public Methods and Properties

Now that the class modules are established, we need to write the methods and properties for the two classes. In both class modules, you can declare public and private methods, properties, and constants for the class.

Private declarations to be hidden in your applications—not accessible by controlling applications—can be implemented as private procedures in a standard Visual Basic module or as private members in a class module. OLE automation objects are public declarations implemented as public methods and properties in public class modules. Class methods are defined as Functions and Sub procedures within the class modules; properties are defined as public variables, constants, or property procedures.

Calc Class

In the Calc class module we define two variables, one Public and one Private. The Public variable, ThisText, is directly accessible by controlling applications while the Private variable, ThisNum, is accessible only from within the class. We can directly set the values of Public variables within the object application and from controlling applications. Private variables are accessible through class methods only and not directly by controlling applications.

'Properties
Dim ThisNum As Integer
Public ThisText As String

We now define the methods specific to our class. The first Public method is Mult(), which accepts two values from a controlling application, multiplies them together, and returns the result. As you may have noticed, the code for this function is identical to the definition of a function in a standard Visual Basic module. Because the function is defined as Public in a public class module the function is accessible by controlling applications. If defined as Private, the function would be visible to the class module only (see Listing 12.2).

Listing 12.2 OLESRVR.MAK Methods in the Calc Class Accessible by External Client Applications

'Multiply two values
Public Function Mult(X As Integer, Y As Integer) As Integer
Mult = X * Y
End Function
'Property function to retrieve values
Public Property Let Value(X)
ThisNum = X
End Property
Public Property Get Value()
Value = ThisNum
End Property

The two property procedures define operations that occur on properties. Similar to a function, a Property Let procedure is a procedure that can take arguments, execute a series of statements, and change the value of class properties as required. Unlike a function, however, you can use a Property Let procedure only on the left-hand side of a property assignment expression or Let statement. For instance, a controlling application would use a Property Let Value(X) procedure as follows:

Dim AutoSrvr As Object
Set AutoSrvr = CreateObject("AutoSrvr.Calc")
AutoSrvr.Value = 10

As you can see, the Property Let procedure is assigned a value as though it were a standard variable. Visual Basic takes the value of 10 from the assignment and passes it to the Value procedure as the X argument of the procedure.

Property Get procedures are similar to functions in that they can be used on the right-hand side of an expression in the same way you use a function to return values. The Property Get procedure returns the values of and performs operations on properties of a class. For instance, a controlling application would use a Property Get Value() procedure as follows:

X = AutoSrvr.Value

As is shown in the sample code above, X is assigned the value of the property from the value returned by the Property Get procedure. Visual Basic gets the value from the ThisNum private variable and returns it to be stored in X.

Visual Basic determines which property procedure to execute based on the position of that procedure in an expression. The property procedures located on the left-hand side of an expression notify Visual Basic that it is to call a corresponding Property Let procedure. Property procedures on the right-hand side of the expression inform Visual Basic to call the corresponding Property Get procedure. If you are assigning objects, you can also write statements for a Property Set procedure that would be located on the right-hand side of an expression in a controlling application.

Note: In most cases, it is preferable to use property procedures when accessing class properties. Within a property procedure you can write statements that can perform some level of error checking, validation, or calculation before performing a assignment to or retrieval from the respective property of the class.

Picture Class

The Picture class is much simpler than the Calc class in that we are only defining one Public Sub and no properties. The Sub creates a new form and loads a picture, specified by the controlling application, into a picture control on the form, shown in Listing 12.3.

Listing 12.3 OLESRVR.MAK Method of the Picture Class

'Load a picture into a new form
Public Sub DispPicture(Picfile As String)
'Create a new form instance
Dim PicForm As New Form1
'Load a picture into the picture control
PicForm.Picture1.Picture = LoadPicture(Picfile)
'Show the form
PicForm.Show
End Sub

The Sub first creates a new form using the New operator and stores the reference to the form in PicForm. This form is a new instance of a form containing a picture control created for the object application. The LoadPicture() function uses the name of the picture passed by the controlling application in the Picture parameter. The loaded picture is stored and displayed in the picture control Picture1 located on the new form. Each time that this Sub is called from a controlling application, a new form is created to display the specified picture.

Scoping Issues

When developing classes for your object application, you should take care when determining the visibility of your methods and properties. Because we are managing class modules and controlling applications, standard Visual Basic modules, and forms, you must properly determine the scoping of your methods and properties throughout your application.

Some general items that you should pay attention to are as follows:

Object application classes can expose properties and methods of any public OLE automation data type. Some of the public data types include the following:

On the other hand, object applications cannot expose to controlling applications properties and methods of private data type instances within a given object application. The class instances (objects) that cannot be exposed to controlling applications are as follows:

In object applications, public methods or properties in a public class can have an argument or return a value with a type of a private class. For instance, you can create an object variable of type RecordSet that would have the standard set of properties and methods of the Visual Basic RecordSet class. However, you cannot declare a public variable of type Form, because an object of type Form cannot expose public properties, be used as a public return type, or be passed in a public argument list.

Note: Arrays and fixed-length strings must be declared as Private in class modules because they are user-defined data types.

In your object application, try to avoid using public variables outside of the class module in which the variable is defined. Because multiple instances of class objects can exist simultaneously, they can also share any application-wide global data. If you make the assumption that a single object is the only object accessing a particular global data, you could run into a situation where each object of the class may change the one global data, producing erroneous results.

Initialization Code

Each class module has Initialize and Terminate events built-in to allow you to write code to be executed when an object of a class is instantiated or destroyed. When a class is first initialized, Visual Basic executes the Initialize procedure to perform operations on the instantiated object before any other code is executed—also known as a constructor.

When an object for a given class is terminated, Visual Basic executes the Terminate procedure to the class immediately before the class is destroyed—as known as a destructor. In Visual Basic 4, you can define additional methods specific to your class only, but you cannot define additional application events in class modules. The event procedures are selected by first selecting Class in the Object list then selecting Initialize or Terminate from the Proc list.

Application Object

Each object application should have an Application object that maintains information specific to the application. This information is made available to controlling applications in the form of properties or property procedures.

To create an Application object for your application, first create a class, AppClass, that contains properties to describe your application. To initialize the Application object, declare a public variable in a standard module of the object application that references the class.

Public GlobalApp As New AppClass

In each class you create for your object hierarchy of your object application, you will define the Application object. If you decide that a class module in the object application has an Application property, include the following declaration at the class module level:

Public Application As AppClass

In the Initialize event procedure of each class module, assign the instance of the Application object for your class to an Application property for the class.

Set Application = GlobalApp

Through the above steps, each instance of a class can contain an Application property, which is a reference to single instance of the Application object. An Application object cannot be used to create multiple instances of a Visual Basic object application because the same Application object serves all controlling applications that access the object application.

Finalizing the Created OLE Server

Once the classes are created and the methods are completed, you can continue to finalize the application. The first thing to look at when completing an OLE server is to determine whether or not you will require a user interface. This is important since, in some cases, you will need direct interaction with the classes while in other you can simply use the interface of the controlling application. To complete the task, you can select the desired options for compilation of the object application then compile the application for execution.

Developing a User Interface

Although the classes you create in Visual Basic cannot support visual editing, you can have them display forms from your Visual Basic object application. In general, object applications fall into one of the following three categories with regards to user interface:

There is no mandate requiring a user interface for your application. If you want to display a user interface, however, you need to include a form in your object application. For example, the Picture class of our object application uses the Form1 form. For each instance of the Picture class you have one instance of Form1 loaded to display a picture.

An object application must have a designated starting place, whether it is a form (in the form of a user interface) or a procedure. Because this object application has a user interface, the starting place will be Form1. To specify this starting form, the name of the form, Form1, is selected in the Startup Form field of the Project tab in the Tools, Options dialog box. Because Form1 is the starting place of the application, that form is going to be displayed the first time the object application is called to create an instance of a class. When the form is displayed, the form's Load event will be called before the object's Initialize event.

If we were not going to have a visible user interface but only provide objects to other applications, the Startup Form field should be set to Sub Main of the Project tab in the Tools, Options dialog box. Sub Main is a procedure that you declare in a Visual Basic module that contains initialization code for the application. If necessary, you can leave the procedure empty; however, there must be a Sub Main procedure if no form is to be used.

Sub Main()
'Your initialization code goes here
End Sub

Caution: A Sub Main in a class module is treated as an object method named Main, not as a startup procedure. In order for Visual Basic to use a Sub Main, it must be defined in a global module. Do not attempt to pass an instance of a form as a return value or as a ByRef argument to an object's method. Forms are instances of private classes that cannot be used outside of the project. Forms are not exposed as classes or members of a class.

Choosing Project Options

The Project tab of the Tools, Options dialog box (see fig. 12.7) allows you to set the Project Name, StartMode, and Application Description properties for the project. This information is required for an object application to establish information for the system registry and application operation.

Fig. 12.7 Project properties allow you to establish the characteristics of the resultant application.

• The Project Name is used as the projectname argument in the CreateObject() and GetObject() statements. For this object application, set the Project Name to AutoSrvr. When controlling applications attempt to access this application, the statements would be as follows:

Set variable = CreateObject("AutoSrvr.Calc")
Set variable = CreateObject("AutoSrvr.Picture")
Set variable = GetObject(,"AutoSrvr.Calc")
Set variable = GetObject(,"AutoSrvr.Picture")

The StartMode option determines whether your application is a standalone executable or an OLE automation server. For this application, select the OLE Server option.

The text you enter in the Application Description field will be used in the Tools, References dialog box to identify your object application to controlling applications.

Note: You can set the Description and HelpContextID properties for each method and property of a class through View, Object Browser. For each class you can set Description and HelpContextID values for only public methods, property procedures, and the class itself. You cannot set these values for properties defined simply as data members.

Running the Application

In the Visual Basic environment you can run the object application by choosing Run, Start. Once elected, Visual Basic registers your object application's classes with the system registry for access by controlling applications. You can now run a controlling application to gain access to and manipulate the object application's classes.

Using a Visual Basic OLE Server

The purpose of developing an object application is to expose objects that provide functionality to accessing controlling applications. Controlling applications that access those objects decide which objects to use and when to use them; the object application merely provides the requested objects to the requester. To provide visibility of object applications for use, the object application must first be registered in the system registry. Once registered, OLE automation starts your object application when a controlling application requests the services of an object from the object application.

With Visual Basic, you can create object applications in the form of executable (EXE) files that supply object libraries. You cannot create object applications as Dynamic Link Libraries (DLLs) with Visual Basic 4.

Registering an OLE Server

You have seen how the system registration database contains information about all object classes and their servers installed on the user's machine. To make this scheme work, all server applications should register themselves in the server registration database, preferably at the time of installation.

To register a Visual Basic application you should run the application with the /REGSERVER on the command line. This will start your object application, have it register its classes with the system registry, then shut down and wait for requests by controlling applications. If you run you object application for the first time without the /REGSERVER on the command line, the server application will register its classes and then remain running.

olesrvr /REGSERVER

To verify that the application is registered, look in REGEDIT to see registered classes. As shown in figure 12.8, the AutoSrvr object application of this chapter is registered in REGEDIT and can provide its objects, Calc and Picture, for use by controlling applications.

Fig. 12.8 Once registered in the system registry, the AutoSrvr server application is available for access by controlling applications.

Removing an Object Application from the System Registry

As you develop your application and run different versions repeatedly, especially when debugging, the OLE system registry may get filled with obsolete entries. It is a good idea to clean out the registry periodically to keep it at a minimum size. You can remove these entries from the registry in the following two ways:

• You can run the older versions of your object application with the /UNREGSERVER command-line argument.

• You can use REGEDIT.EXE periodically to remove entries of obsolete versions of your object application. REGEDIT.EXE includes a Help file with online instructions (see fig. 12.9).

If you run your object application with the /UNREGSERVER option, Visual Basic deletes the following keys in the system registry:

• The matching ROOT entry (such as projectname.class), regardless of whether the value of the CLSID key in the ROOT entry matches the CLSID of the object application.

• The matching CLSID entry.

• The matching Interface IDs for the interfaces that the EXE file supports.

Fig. 12.9 REGEDIT provides a search facility that enables you to rapidly locate entries in the system registry.

Starting an Object Application

OLE automation automatically starts your object application when a controlling application requests an object from your application. At that point, the object application is started, a new instance of the requested class is created, and OLE passes an object reference to the controlling application after the object's Initialize event has completed.

Once running, the object application provides new objects to all controlling applications that request them. One instance of the object application can supply several objects and multiple copies of those objects to requesting controlling applications.

In Listing 12.4, we are starting the AutoSrvr object application from Excel using Visual Basic for Applications. Applications that support VBA, such as Microsoft Excel 5.0, can be used to access and manipulate the functionality of object applications.

Listing 12.4 SRVRDBG.XLS Creating a Calc Object from Excel 5.0 VBA

Sub TestAutoSrvr()
Dim x As Object
Dim aa As Integer
Dim bb As Integer
aa = Application.ActiveSheet.Cells(1, 1).Value
bb = Application.ActiveSheet.Cells(1, 3).Value
Set x = CreateObject("AutoSrvr.Calc")
MsgBox Str(x.Mult(aa, bb))
Application.ActiveSheet.Cells(1, 5).Value = x.Mult(aa, bb)
End Sub

From Excel we can access all of the objects' public methods and properties, thus the functionality of the object application's classes. In the application of Listing 12.4, we obtain values from cells within the active worksheet within Microsoft Excel using the Application.ActiveSheet.Cells(x, y).Value. The application then creates and instance of our Calc class using the CreateObject("AutoSrvr.Calc") function.

We then take the values and multiply them using the x.Mult(aa, bb) methods of the new object. The resulting value is then stored into a cell within the active Excel worksheet.

Once your object application is started, Visual Basic keeps track of the number of times an object is requested by one or more controlling applications. When the last of these instances is closed, Visual Basic closes your object application. One point to keep in mind is that you cannot close a controlling application from your object application, but you can close an object application from a controlling application.

Debugging Your Object Application

As with any code that you develop, you need to test and debug your object application once it is coded. Testing can be accomplished within the Visual Basic development environment by having two instances of Visual Basic: one instance running the object application, and a second running a controlling application. Figure 12.10 illustrates one Visual Basic instance running a simple controller and another running a server. Visual Basic does not allow you to run separate projects in one instance of Visual Basic, so you have to run multiple instances of Visual Basic, each with a different project, simultaneously.

Fig. 12.10 In some circumstances, you may run multiple versions of Visual Basic to debug your object applications.

You are not required to make an executable file of an object application to debug it. However, the object application must be an executable file before it can be permanently registered in the system registry. When debugging your object application, Visual Basic makes temporary entries in the system registry and deletes them when you finish the debugging session.

You can also debug your application from a controlling application other than Visual Basic. As shown in figure 12.11, we are running Microsoft Excel as a controller for a small Visual Basic object application.

Fig. 12.11 Excel can be used to debug Visual Basic object applications.

The following steps detail how to debug Visual Basic object applications:

1. Using Visual Basic, set breakpoints in your class module code where required and set up watch expressions for class module variables that you want to monitor while your object application is running.

2. Ensure that an existing version of your object application is not already running. If it is, existing references to the object application and the classes it exposes may not be valid and the debugger may not operate properly on the proper version of the application.

3. Run the object application and, using the debug facility of Visual Basic, verify the operation of the object application.

4. Start a second instance of Visual Basic as the controlling application and open a new project.

5. While in the controlling application project, choose Tools, References from the Visual Basic menu and make sure that the object application, located in the other instance of Visual Basic, is selected.

6. In the controlling application project, choose View, Object Browser to check that all intended public methods and properties from the object application are displayed. If some are not, make sure that you have properly declared them as Public members in a public class module.

7. In the controlling project, declare and set a variable of a class defined in the object application. If you try do this using the CreateObject() and it fails, make sure that the class module defining that class does not have its Instancing property set to Not Creatable.

8. In the controlling application project, write code that creates and manipulates objects from the classes of the object application. Make sure that you test all of the functionality intended for the object application.

9. When the controlling application invokes an action that jumps to a watch expression or breakpoint in the object application, the object application will stop and receive focus. Visual Basic displays the object application's class module in the Debug window of the first instance of Visual Basic. It displays the controlling application's modules in the Debug window of the second instance of Visual Basic.

Caution: Debugging may cause artificial changes in focus that prevent continued execution from behaving as expected. You should be careful to avoid debugging situations that are sensitive to focus or activation events, especially mouse and key events.

Running Multiple Application Versions

Once your object application is fully debugged so that an instance of each class can be successfully created and used, you may want to run several Visual Basic controlling applications simultaneously to simulate multiple instances of classes being created and used.

Visual Basic is capable of running two object application projects simultaneously. If the class names conflict between the applications, however, the second project will overwrite the registry entries of the first object application when the second object application is running. In this case, controlling applications can access OLE automation objects from the most recently started object application only. To remedy this situation, use different project names and class names if you are going to run two or more versions of an object application simultaneously.

Caution: If the controlling application is in runtime mode and you stop running the object application project, the controlling application will no longer be able to access the object application's objects and a runtime error may occur.

Changing Controller References to the Application

After the class modules are defined and debugged, choose File, Make EXE File from the menu to build an executable version of your object application. Once you have successfully made an executable file, go back to your controlling application and use the References dialog box to change the reference from the debug version of your object application to the executable version. Of course, if you don't plan to use the controlling application again, you don't need to do this. But if you do use it after building the object application executable file, the reference to your object application should point to the executable version, not the debug version.

Caution: Do not build an executable file for your controlling application while the debug version of the object application project is running. If you do, the controlling application will reference the temporarily registered version of the object application. When the object application is made into an executable file, that reference will change, and the controlling application will no longer refer to the executable version of the object application.

Standards and Guidelines

Object application developers have adopted a standardized scheme for organizing and naming OLE automation objects and their methods and properties. If you follow these standards when creating an object application, controlling applications can better recognize the purpose of a method or property.

The next few sections discuss standard OLE automation, naming guidelines for creating OLE automation objects. If your object application does not have a visible interface or supports a single document interface only, you should adapt the standards and guidelines as appropriate.

Standard Objects

Standard objects, a set of objects defined by OLE, should be used as appropriate in your application. The OLE automation objects described in this chapter are oriented toward document-centric applications. Other applications that don't have a visible user-interface may have requirements different from those described here.

The naming guidelines are recommendations meant to improve consistency across applications. In this way controlling applications can easily interface with many different object applications using a standard naming convention.

The following list has the standard OLE automation objects and their methods and properties. Although none of these objects is required, it is recommended that applications with dependent objects include an Application object.

The following sections describe the standard properties and methods for all objects, and then more specifically for collection objects and the Application object. These sections list only standard methods and properties for each object, as well as the standard arguments for those properties and methods.

Note: You may define additional application-specific properties and methods for each object. You may also provide additional optional arguments for any of the listed properties or methods; however, such optional arguments should follow the standards for argument lists.

Properties Required

All objects, including the Application object and collection objects, should provide the following properties:

A collection provides a mechanism for storing objects that can be indexed and searched. All collection objects automatically provide the Count property, which is read-only and returns an integer data type containing the number of items in the collection.

Collection Methods

The following list describes methods available for the Collection object. You cannot extend the members of the Collection object, but you can create your own collections in Visual Basic class modules.

The Item Method

All collection objects must provide at least one way of indexing through the items of the collection. Because Item is the default method for collection objects, it can be used in the following form:

ThirdDef = MyWords(3).Definition

Item takes one argument, an index, which can be a number, string, or other data type. When declaring the Item method, use the following syntax:

Function Item (index As Variant) As Variant
DogDef = MyWords("dog").Definition

You should take into account the following when using the Item method:

Print MyCollection(1)
Print MyCollection.Item(1)

The Add Method

The Add method takes four arguments, as shown in the following code:

Sub Add (item As Variant [, key As Variant]
[, before As Variant] [, after As Variant] )

You can omit the three optional arguments. In Listing 12.5, for example, MyWord is an object with the properties Letters and Definition:

Listing 12.5 Managing Information in a Dictionary

Dim MyWord As New Word
Dim MyDictionary as Words
MyWord = "dog"
MyWord.Letters = "Dog"
MyWord.Definition = "My best friend."
MyDictionary.Add MyWord
MyDictionary.Remove("Dog")

You should take into account the following when using the Add method:

The Remove Method

The Remove method takes one argument, index, that points to the item in the collection to remove. You should take into account the following when using the Remove method:

Application Object Properties and Methods

For an object application, the Application object should have the following standard properties.

Naming Guidelines

You should choose names for exposed objects, properties, and methods that can be easily understood by the users of your application. The following guidelines apply to all objects, properties, methods, and constants:

Use entire words or syllables whenever possible.

From Here...

In this chapter we discussed the development and implementation of OLE server applications. We looked at the different types and capabilities of servers and how they fit into the OLE hierarchy. After the discussions of server development we stepped through the debugging process of an OLE server. Finally we discussed some of the standards required by OLE servers to provide a common interface for each distributed object application.


| Previous Chapter | Next Chapter | Search | Table of Contents | Book Home Page |

| Buy This Book | Que Home Page | Digital Bookshelf | Disclaimer |


To order books from QUE, call us at 800-716-0044 or 317-361-5400.

For comments or technical support for our books and software, select Talk to Us.

© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.