Valor Whisler
President, Semiotix Systems
June 27, 1995
Valor Whisler is president of Semiotix Systems, a Colorado corporation in the business of developing engineering tools for Visual Basic. Semiotix is the publisher of VB AppFramework, an add–in that acts as a repository for Visual Basic code and object templates and styles. Whisler subscribes to the theory that OLE will provide the platform for the creation of extremely sophisticated and complex applications by supporting the assembly of commercial and custom component objects.
As Whisler relates the story, after seeing Visual Basic for the first time a couple of years ago, a colleague lamented that the days of the programmer were over and the days of the "application designer" were just beginning. His point was well taken: Tools such as Visual Basic add–ins will take the software industry a step closer to this prediction.
Microsoft® Visual Basic® version 4.0 exposes its development environment through a set of objects collectively known as the Visual Basic Integrated Development Environment, or Visual Basic IDE. Using these objects, programmers can obtain information about projects and manipulate those projects at design time. To facilitate such interaction, programmers also can create add–ins, which can provide any level of sophistication and interface. In their simplest form add–ins can augment tedious or repetitive tasks. In more sophisticated incarnations, add–ins can provide complete modeling front ends that generate forms or entire application frameworks. In much the same way that diverse vendors have come forward to supply custom controls for Visual Basic, vendors also can be expected to create a multitude of add–ins. The result will be an environment that takes software developers further from the role of a programmer and closer to that of an "application designer."
Everyone has read phenomenal predictions regarding what computing will look like in the years to come. Every business in the software industry is pressured to bring increasingly sophisticated programs to completion faster.
In response, Microsoft has equipped the Visual Basic programming system with a variety of high-level services for rapid application development. As the product has evolved, its performance and capabilities have increased dramatically. Microsoft designed Visual Basic as an open design environment for which third-party vendors could produce extensions. Up to now such extensions have appeared in the form of custom controls, including Visual Basic extensions (VBXs), and OLE Controls, both of which are available from many generalized, or application-specific suppliers. Visual Basic enables developers to exploit this technology by providing a platform incorporating diverse components into a homogeneous solution.
Figure 1. Visual Basic interaction with Add–Ins and Custom Controls
Visual Basic add–ins and other next-generation tools will provide a new direction for extending the product's capabilities and will enable software developers to create an infrastructure that will profoundly change the way they work. Such tools will "drive" Visual Basic to perform increasingly complex and sophisticated tasks, transforming application development just as macros changed the way spreadsheets are used—but with far greater potential.
In Visual Basic 4.0, the development environment is exposed as an OLE object that can be easily manipulated by specialized OLE servers called add–ins. They are considered specialized because an OLE server designed as a Visual Basic add–in must have two predefined methods: ConnectAddIn, which informs an add–in that Visual Basic is using it, and DisconnectAddIn which informs an add–in that Visual Basic is no longer using it. Once it is connected to Visual Basic, an add–in can obtain information about the development environment and manipulate much of that environment.
Any language capable of creating an OLE server can create Visual Basic add–ins. Even better, the add–ins can be created by Visual Basic itself.
Looking back at Visual Basic 1.0, few developers would have predicted the robust and diverse set of add–ins available to complement Visual Basic 4.0. Similarly, developers might find it hard to predict what such capabilities will ultimately mean—but they might enjoy trying. In their simplest use, add–ins can automate development tasks in the same way macros automate spreadsheet tasks. Such automation may materialize in the form of wizards or through an interface designed to suit a specific audience. In more sophisticated implementations, add–ins can provide complete front ends, enabling developers to model systems in any number of ways. Such models can then be used to generate a Visual Basic project and supporting code. The following are a few of the possibilities:
As noted earlier, the set of objects and events collectively exposed by Visual Basic is known as the Visual Basic Integrated Development Environment, or Visual Basic IDE. This set of objects and events is made available to add–ins through an object library. To use this library, developers should add the reference Microsoft Visual Basic Development Library (VBExt16.olb or VBExt32.olb) to Visual Basic using the References dialog under the Tools menu.
The Visual Basic IDE provides four categories of objects and events: AddInMenu objects, ActiveProject objects, ConnectAddIn and DisconnectAddIn events, and FileControl events.
The AddInMenu objects enable the add–in to create and remove menus and submenus. In Visual Basic, these custom menu items reside directly under the Add–Ins menu.
The ActiveProject objects provide capabilities for complete interaction with forms and controls. They also provide the capability to add blocks of code to any code window.
The ConnectAddIn and Disconnect AddIn events are required by an OLE server to be recognized by Visual Basic as an add–in. Visual Basic calls these events, respectively, when an add–in is connected or disconnected from a project. These events are used to initialize and terminate the environment provided by the add–in.
The FileControl events are a set of events that an add–in may optionally expose to Visual Basic. If they are found within a class module, Visual Basic will call them in response to various file activities.
The Visual Basic IDE exposes itself as a set of objects in a specific hierarchy, structured to be consistent with the organization of other OLE objects, such as the DAO object library. Visual Basic IDE objects come in two primary types: collection and member. A collection is an object containing a set of related objects. The objects found within a collection are referred to as members. Objects are manipulated by setting their properties and invoking their methods.
Every collection object contains the properties Application, Parent, and Count as well as the method Item. Some collections may have additional methods. In contrast to the organization of an array, member order within a collection is not guaranteed. For this reason, the preferred method of iteration through a collection is to use the For-Each construct. The properties and methods of member objects vary from object to object.
The following figure shows some of the collection and member objects exposed by the Visual Basic IDE. The hierarchy depicted in the figure would read as follows:
Figure 2. Some Collection and Member Objects exposed by Visual Basic
The object browser lists the properties and methods for each object contained within the library, enabling developers to examine the contents of an object library. Appearing in the form of a dialog, the object browser is a particularly useful tool. It is easy to access, and the information it reveals comes directly from the object rather than from a text or help file. For this reason, developers can be confident that the information listed corresponds directly to the objects, properties, and methods that are exposed.
Objects contained within the Visual Basic IDE can be manipulated from within an add–in using object variables. These are variables of the data type "object"—a collective term describing OLE objects in general. Using this "implicit object reference" approach, developers would create variables of general object types, also referred to as "late binding". This is illustrated in the following example:
Dim ThisProject As Object Dim ThisForm As Object Set ThisProject = VBInstance.ActiveProject Set ThisForm = ThisProject.ActiveForm
Developers also can create a variable of the specific type of object they intend to use. This "explicit object reference" approach, also called "late binding", provides a much more efficient method of referencing objects, because under this method the compiler does not need to resolve the object type before using it. Variables of specific object types would be created as shown:
Dim ThisProject As ProjectTemplate Dim ThisForm As FormTemplate Set ThisProject = VBInstance.ActiveProject Set ThisForm = ThisProject.ActiveForm
To handle the case in which identically named collections or members reside in different object libraries, developers can preface the object reference with the name of the library in which the object reference resides. For example, an object named Properties is used in the Visual Basic IDE and in the DAO libraries. The following code segment illustrates how to resolve this conflict:
Public TheseIDEProperties As VBIDE.Properties Public TheseDAOProperties As DAO.Properties
An add–in is a special kind of OLE server that contains predefined events called by Visual Basic. As part of add–in creation, developers must inform Visual Basic of the add–in by adding entries to the VB.INI file. Developers also must provide an interface, typically a set of menus, for the add–in.
An add–in has the following attributes:
The Application object (Visual Basic) provides the capabilities to create and remove menus for add–ins. Each such menu item must be connected to a class object (an instance of a class module) contained within the add–in. A class object referenced in this way must contain the AfterClick event, which will be called when the add–in menu item is clicked.
The add–in must manage its menus, including their creation, or Setup, and removal, or Cleanup, as illustrated by the following:
The Application object (Visual Basic) contains an object named AddInMenu, which is an instance of the Visual Basic Add–Ins menu. AddInMenu contains a MenuItems collection representing all of the entries in the Add–Ins menu. An add–in can create and remove menu items using methods provided by the AddInMenu object. Each menu item that is to perform a task when clicked is connected to a class object contained within the add–in.
The following code segment illustrates how an add–in creates a top-level menu and two submenus:
'instances of class modules------------------------------ Public clsDataWizard As New DataWizard Public clsOptions As New Options 'reference to the Visual Basic application--------------- Private ThisVBInstance As VBIDE.Application 'primary menu ------------------------------------------- Private ToolMenu As VBIDE.Menu 'sub-menu items------------------------------------------ Private DataMenuLine As MenuLine Private OptionsMenuLine As MenuLine 'event tokens-------------------------------------------- Private DataEventToken As Long Private OptionsEventToken As Long Public Sub ConnectAddIn(VBInstance As Object) 'store the application object, needed to disconnect-- Set ThisVBInstance = VBInstance 'set up main menu------------------------------------ Set ToolMenu = VBInstance.AddInMenu.MenuItems.AddMenu("&Tools") 'set up sub-menus------------------------------------ Set DataMenuLine = ToolMenu.MenuItems.AddMenu("&Data Wizard") Set OptionsMenuLine = ToolMenu.MenuItems.AddMenu("&Options") 'hook menu items to class objects-------------------- DataEventToken = DataMenuLine.ConnectEvents(clsDataWizard) OptionsEventToken = OptionsMenuLine.ConnectEvents(clsOptions) End Sub
Each class object must contain the AfterClick event. This event will be called when the menu item in the Visual Basic project is clicked, as illustrated in the following code segment:
'this public sub is called when the Options menu item is clicked Public Sub AfterClick() frmOption.Show vbModal End Sub
When the instance of Visual Basic supplying the Application object is exited, or when the add–in is removed from the add–ins dialog, the add–in will receive a disconnect event. It is within this event that the add–in should disassociate the class objects from the menu items and remove the menus themselves. These activities are illustrated by following code segment:
Public Sub DisconnectAddIn(Mode As Integer) 'unhook menu items from class objects---------------- DataMenuLine.DisconnectEvents DataEventToken OptionsMenuLine.DisconnectEvents OptionsEventToken 'remove sub-menus------------------------------------ ToolMenu.MenuItems.Remove DataMenuLine ToolMenu.MenuItems.Remove OptionsMenuLine 'remove main menu------------------------------------ ThisVBInstance.AddInMenu.MenuItems.Remove ToolMenu End Sub
An add–in can obtain information on Visual Basic by traversing the hierarchy of collection and member objects provided by the Visual Basic IDE. (For more detail on this hierarchy, refer to the Visual Basic documentation.) The Visual Basic IDE provides complete information on forms, controls, and menus, and some information on the components contained within the project. The Visual Basic IDE does not currently provide information about code contained within forms, code modules, or class modules.
As developers traverse the object hierarchy, additional objects—and, ultimately, properties—become available. The hierarchy begins with the Application object that was passed into the add–in during the ConnectAddIn event. The add–in should set a variable of type Object or VBIDE.Application to this incoming object. (For purposes of this discussion, the variable ThisVBInstance is assumed to be that object variable.) The add–in can then create a fully qualified reference to any particular object and for convenience can set intermediate objects along the way.
Dim ThisActiveForm As FormTemplate Dim TheseControls As ControlTemplates
The following are fully qualified object references to the controls on a form:
Set TheseControls = ThisVBInstance.ActiveProject.ActiveForm.ControlTemplates
The following is the same reference using an intermediate object:
Set ThisActiveForm = ThisVBInstance.ActiveProject.ActiveForm Set TheseControls = ThisActiveForm.ControlTemplates
The following table summarizes how Visual Basic IDE objects are used to perform various tasks and obtain information about the project. (Please note that object references have been shortened from the full reference that is actually required.)
Task |
Uses Object |
Gets Object or Value |
Get the active form |
ActiveProject.ActiveForm |
FormTemplate |
Get the active component |
ActiveProject.SelectedComponents.Item(0) |
Component |
Get the selected controls |
ActiveForm.SelectedControlTemplates |
ControlTemplates collection |
Get all controls |
ActiveForm.ControlTemplates |
ControlTemplates collection |
Get all menus |
ActiveForm.ControlTemplates |
ControlTemplate of ClassName: Menu |
Get all properties of a control |
ControlTemplate.Properties |
Properties collection |
Get the name of a control |
ControlTemplate.Properties.Item("Name") |
The value of the property: Name |
Get the background color of a form |
ActiveForm.Properties.Item("BackColor") |
The value of the property: BackColor |
For many tasks an add–in will be required to iterate through a collection. For example, for information on all the menus on a form, the add–in will need to examine the ControlTemplates collection. (Note that a menu cannot be a member of the SelectedControlTemplates collection because it cannot be selected at design time.) The preferred method for these iterations is the For-Each construct. The following code segment, which receives as its argument the active form in the project, illustrates how the menus would be located:
Public Function CountMenus(ThisForm As FormTemplate) As Integer Dim InstanceControl As ControlTemplate Dim TheseControls As ControlTemplates Dim MenuCount As Integer Set TheseControls = ThisForm.ControlTemplates For Each InstanceControl In TheseControls If (InstanceControl.ClassName = "Menu") Then MenuCount = MenuCount + 1 End If Next CountMenus = MenuCount End Function
Methods and properties can manipulate a Visual Basic project and objects within the project. As with the query process, an add–in must traverse the object hierarchy and obtain an object with which to work. In this regard, working with Visual Basic IDE objects is like working with a Visual Basic project, as illustrated in the following:
The following table outlines the ways that developers can manipulate a Visual Basic project using the Visual Basic IDE. (Please note that object references have been shortened from the full reference that is actually required.)
Task |
Uses Object |
Method or Property |
Add a file to the project |
ProjectTemplate |
AddFile |
Create a new form |
ProjectTemplate |
AddFormTemplate |
Add a control to a form |
FormTemplate.ControlTemplates |
Add |
Add a menu to a form |
FormTemplate |
AddMenuTemplate |
Change the property of a control |
ControlTemplate.Properties |
Item("PropertyName") = value (PropertyName is the name of the property to change) |
Place a control in a new container |
ControlTemplate |
Container = NewContainer (NewContainer is a valid container object of type ControlTemplate, or FormTemplate) |
An add–in is a specialized OLE server that exposes some predefined events. Visual Basic compiles a project as an OLE server by changing the StartMode option found in the Project property sheet of the Options dialog. Although Visual Basic does not require that any particular methods or properties be contained within the class objects provided by the add–in, OLE guidelines recommend that all OLE servers conform to certain standards. These standards suggest common properties and classes that servers should expose. Discussions of these standards can be found in such references as OLE 2 Programmers Reference and Inside OLE 2.