Click Here to Install Silverlight*
United StatesChange|All Microsoft Sites
MSDN
|Developer Centers|Library|Downloads|Code Center|Subscriptions|MSDN Worldwide
Search for


Advanced Search
MSDN Home > MSJ > August 1997
August 1997


Code for this article: VisualProg0897.exe (1KB)
George Shepherd develops mapping software for Orbital Software and delivers training courses for DevelopMentor. Scot Wingo is cofounder of Stingray Software, producing MFC extension class libraries. George and Scot wrote MFC Internals (Addison-Wesley, 1996).

Q I'm trying to learn more about the ActiveX Designer support in Visual Basic® 5.0. What can you tell me about it?

A "Designer" is a term used by Microsoft to denote a component that's useful for developing applications. The best way to understand the nature of a designer is to take a look at an example.
A designer is a high-level software component that includes, among other things, dedicated design-time support. When you want to pump out a Visual Basic-based application, what's the first thing you usually start working with? For most developers, the answer is a form. A Visual Basic form is an example of a designer. Whenever you ask Visual Basic to add a new form to your application, you get something akin to a blank window ready to house controls and intercept events. The form maintains a set of properties, including a window style and a caption that you can program at design time. When the application actually runs, the runtime aspect of the form uses the information provided by the developer at design time to display the correct controls and respond to events appropriately.
While the Visual Basic Form Designer (the one you get for free with Visual Basic) is very useful, it isn't the only designer available. Microsoft supports other designers that use ActiveX technologies. They're called (not surprisingly) ActiveX Designers.

What's an ActiveX Designer?

An ActiveX Designer is similar to a regular form in that you use it to create Visual Basic classes. ActiveX Designer-produced classes fit into your application just as form classes do. In addition, you can program the classes by changing properties and attaching code. However, ActiveX Designers are not confined to producing forms; they can do pretty much anything you want them to.
For example, if you develop kiosk-type point-of-sale systems, you can encapsulate much of your domain-specific user interface and code using an ActiveX Designer that produces a form with some domain-specific boilerplate code already in it. Then, instead of starting from scratch using a standard Visual Basic form for creating new applications, you can save yourself some time by starting off with a form created by the ActiveX Designer. An ActiveX Designer can be as simple as an object that makes itself visible at design time or as complex as a form that hosts controls.
ActiveX Designers implement most existing ActiveX technologies, including Automation, COM persistence, COM embedding and rendering, events, and property pages. ActiveX Designers also throw in a couple of other concepts, including services and dynamic type information (which you'll see later).

ActiveX Designers Versus ActiveX Controls

ActiveX Designers and ActiveX controls are actually similar beasts that share several characteristics. For example, they are both embeddable objects that expose functionality through IDispatch. Also, they can both have different behavior at design time and runtime. (An ActiveX control can detect whether it's in design or run mode by using an ambient property.) In addition, they can both be programmed by the user.
After looking at the list of technologies used by ActiveX Designers, you might be wondering how they are different from ActiveX controls. In truth, an ActiveX control can qualify as an ActiveX Designer, albeit a limited one, with just a few extra registry entries because they are so closely related. The major difference between the two is that an ActiveX control is a single COM class while an ActiveX Designer may be divided into two separate COM classes—the design-time class and the runtime class. In addition, ActiveX Designers maintain several more registry entries. Finally, ActiveX Designers usually take advantage of some new ActiveX technologies—namely, the ActiveX service architecture and dynamic type information. To understand how ActiveX Designers work, let's start by examining how they separate design-time and runtime components.

Design-time Versus Runtime Components

ActiveX Designers usually maintain two personalities: a design-time personality (referred to as a visual designer), and a runtime personality (referred to as a runtime object). The visual designer provides the means by which developers create objects based on the ActiveX Designer. For example, when you create a Visual Basic form, Visual Basic presents a blank window waiting for you to place controls on it and wire some event responses into it. The visual designer handles the ActiveX Designer's presentation and a user interface for managing the object's properties, methods, and events. Finally, developers use the visual portion of an ActiveX Designer to write application-specific code for manipulating the ActiveX Designer-based objects.
Applications developed using ActiveX Designers end up being single executables that use the ActiveX Designer-based runtime object customized to the developer's specification. When the user builds the application, the ActiveX Designer saves the persistent state of the object (GUIDs and so on) so the application can use it. At runtime, the system uses the saved information to load instances of the runtime object.
ActiveX Designers differentiate the runtime object and the visual designer for several reasons. First, the design-time object and the runtime object may differ in implementation. Remember, the design-time object exists to provide a user interface for programming the object at design time. The runtime object will probably not have that same user interface. Second, the design-time and runtime licensing requirements are often different. In addition, some ActiveX Designers may have different type requirements between design time and runtime and, therefore, implement separate design-time and runtime objects.
An example of a designer that looks and behaves differently at design time and runtime might be one that develops design-time queries for databases. Such a designer would probably not need a runtime user interface. Another example is an ActiveX Designer for creating data browser-type objects. The design time version would probably provide developers with many different options for sizing, scaling, and so forth, but might include only a few navigation buttons for the final application.
An ActiveX Designer whose design-time and runtime objects are the same might be used for defining forms. The visual representation of a form is often similar at runtime and at design time, so their design-time and runtime objects are usually the same.

ActiveX Designers and Visual Basic

At this point, the only ActiveX Designer support within Visual Basic is for using ActiveX Designers in an application. The documentation mentions an ActiveX Designer SDK included with the Professional and Enterprise versions of Visual Basic. However, the only thing resembling an ActiveX Designer SDK I've been able to locate is the ActiveX Designer Programmers Reference and sample set on the MSDN CD-ROM.
If you want to see an ActiveX Designer in action, Visual Basic includes one—it's called the UserConnection Designer. The UserConnection Designer provides design-time support for programmatic data access. For example, database connections are traditionally set up at runtime. The UserConnection Designer allows you to develop connections and query objects (based on the RDO rdoConnection and rdoQuery objects) at design time. These connections and queries are managed and saved as project-level objects. That way, you can preset properties, define new properties and methods, and write code behind the objects to catch events.

Using ActiveX Designers

Adding an ActiveX Designer to your project is really no different than adding other components. For example, if you want to include an ActiveX Control, you'd pull down the Project menu, select the Components menu, and then choose the Controls page to pick the ActiveX control you want in your application. Including an ActiveX Designer involves pulling down the Project|Components menu and using the Designers tab. Visual Basic searches the CLSID key under HKEY_CLASSES_ROOT in the registry, looking for any GUIDs that have an Implemented Categories key (with the GUID {4EB304D0-7555-11cf-A0C2-00AA0062BE57}—that's the GUID representing a Designer). Visual Basic puts them in the Designers tab in the Components dialog box. Figure 1 shows the Designer tab in the Visual Basic Components dialog.
Figure 1 Adding a Designer to a Project
Figure 1 Adding a Designer to a Project

Once the designer is in your project, you can add an instance of the designer to your application by selecting the Add ActiveX Designer option from the Project menu. Adding this is similar to adding a new form to your program (see Figure 2). All of a sudden, you have a new programmable object ready to do your bidding.
Figure 2 Adding an Instance of the Designer
Figure 2 Adding an Instance of the Designer

Using the ActiveX Designer in your application is similar to using a form. For example, if you add an instance of the UserConnection Designer, you'll see a set of property pages for setting up a database connection that includes settings for the data source and security (see Figure 3).

Design-Time UI

While the support for using ActiveX Designers in Visual Basic is excellent, the only way to write an ActiveX Designer is to use a language like Visual C++. Let's take a closer look at what goes on inside an ActiveX Designer.
Figure 3 UserConnection Property Page
Figure 3 UserConnection Property Page

An ActiveX Designer uses OLE document technology to implement the design-time portion. Visual Basic manages ActiveX Designers within a frame window at design time (just like Visual Basic handles plain-vanilla forms). The frame is an OLE container that exposes a set of window-like properties, methods, and events and provides a place for the Designer to draw any appropriate visual representation. Visual Basic creates and manages the frame, not the ActiveX Designer. Basically, the visual designer is an in-place embedded object. The ActiveX Designer interacts with the frame through ActiveX interfaces. However, the ActiveX Designer controls its own visual representation within the frame.

Making the Connection

Because an ActiveX Designer is an in-place embedded OLE object, Visual Basic expects the visual designer portion of an ActiveX Designer to implement the following OLE document interfaces: IOleObject, IOleInPlaceActiveObject, and IOleInPlaceObject. To be programmable, a visual designer also implements IDispatch for invoking methods and accessing properties. Visual Basic expects an ActiveX Designer to implement IConnectionPoint and IConnectionPointContainer to set up the event connection. Visual Basic also depends on IProvideClassInfo or IProvideDynamicClassInfo for accessing the type information, and the ActiveX Document must implement at least one of the persistence interfaces (IPersistStorage, IPersistStream, or IPersistStreamInit) to save persistent data from one session to the next. All of these protocols except IProvideDynamicClassInfo have been around since the days of OLE documents and controls.
Adding an ActiveX Designer to your project using the Project menus as described above causes Visual Basic to perform several steps. First, Visual Basic calls CoCreateInstance to create an instance of the visual designer. This is the user interface the developer will use to work with the object. Next, Visual Basic initializes the visual designer using the OLE document embedding protocol. Visual Basic calls IOleObject::SetClientSite to associate the designer with a site within Visual Basic, acquires the ActiveX Designer's IPersistStorage or IPersistStream interfaces calling the method InitNew or Init method to load the designer's persistent data. Finally, Visual Basic shows the visual designer within the frame it creates. Visual Basic creates a default instance of the visual designer in much the same way that it creates a default instance of a form in your application.
One of the new interfaces introduced for designers is IActiveDesigner, which provides Visual Basic with access to a designer's runtime object. If the visual designer doesn't implement the optional IActiveDesigner interface, the host uses one of the persistence interfaces to save data for the runtime object.
If the ActiveX Designer's visual design-time and runtime objects are different, the runtime object should implement IActiveDesigner to provide information about itself. IActiveDesigner also includes a method that provides access to the designer's programmability object via an IDispatch interface. If the designer implements IPerPropertyBrowsing, ISpecifyPropertyPages, and ICategorizeProperties, then you will be able to view and change properties (this is highly recommended).

Object Programmability and Extensibility

Like normal Visual Basic objects, you can extend ActiveX Designer objects by adding code to change the object's behavior. You can customize ActiveX Designer objects by handling events and by adding properties and methods. One of the more interesting aspects of an ActiveX Designer object is that it uses flexible type information. When you insert a Visual Basic object into an ActiveX Designer, the type information for the visual designer has to change to include information about the new instance. The same is true for performing such operations as adding an event.
If an ActiveX Designer implements IProvideClassInfo, then the designer manages static type information that doesn't change throughout the life of the object. If the designer implements IProvideDynamicClassInfo, then the designer supports dynamic type information. Supporting static type information is fairly straightforward: just load the type library for the designer, use ITypeLib to get the type information of the object, and return the ITypeInfo pointer to the client. Supporting dynamic type information is a little more involved, requiring the ActiveX Designer to use the ICreateTypeLib interface to modify the type library at runtime. For example, these type info creation mechanisms implement functions for adding and removing methods and properties from a particular piece of type information.

Programming the Object

In addition to manipulating properties in an ActiveX Designer-based object, you should be able to respond to events. That is, you should be able to add code to a Designer-based object just like you would add code to a regular form. When a user selects an object and clicks View Code, Visual Basic displays the default event procedure for the object. The user can then write code in the procedure and attach it to the object. Of course, if the Visual Basic object is managed by an ActiveX Designer, the ActiveX Designer should also support this kind of code editing. Visual Basic provides this facility. ActiveX Designers hook into that support via another COM technology—the services architecture.

Services

The term "services" describes uniform functionality that an ActiveX Designer might expect from its host. Services are based on groups of related interfaces that perform a task to be implemented by the host. For example, an ActiveX Designer might need to navigate to the code attached to an object. This is a service provided by Visual Basic.
ActiveX Designers access services through their sites. That is, by using the OLE document protocol followed by ActiveX Designers, the frame containing an ActiveX Designer implements an interface named IOleClientSite. IOleClientSite represents the embedded object's anchor in the frame. The interfaces that make up the service may be implemented on the site object or on any other object to which the site has access.
The ActiveX Designer service architecture provides a flexible means for allowing contained objects (visual designer objects) to talk to and obtain services from the host. The services architecture specifies that the client implement IServiceProvider, which has a single function, QueryService, above and beyond IUnknown. QueryService looks like this:

 IServiceProvider : public IUnknown {
    HRESULT QueryService(REFGUID rsid, REFIID riid, 
                         void** pobj) = 0;
 };
As with all other things COM, ActiveX Designer services are named by GUIDs. An ActiveX Designer acquires a service by using IOleClientSite to query for the IServiceProvider interface. Once the ActiveX Designer has the IServiceProvider interface, it may ask for a certain service. So far, there are four services defined for ActiveX Designers:
  • SApplicationObject returns the interface necessary for programming the host's IDE.
  • SCodeNavigate navigates to the code associated with an object.
  • SProfferTypeLib enables components to add type libraries to the project.
  • STrackSelection tracks menu and object selections in a user interface.
For example, Figure 4 shows how an ActiveX Designer might acquire and use the code navigation service.
It may seem odd that services are defined as groups of interfaces rather than as single interfaces. The key difference is that a QueryInterface for a particular object returns an interface pointing to that object, whereas QueryService returns a pointer to an interface that's not necessarily part of an object—it's just an interface representing a service that doesn't necessarily follow the rules of COM identity.

Conclusion

ActiveX Designers open up a whole new world in terms of extending the Visual Basic programming environment. No longer are you stuck with the plain-vanilla forms provided by Visual Basic. With some imagination, you can extend the Visual Basic environment in myriad ways.
ActiveX Designers are also a good example of how COM breaks down the barriers to software integration. Once a standard architecture and set of interfaces are defined for a technology, applications and development tools suddenly become infinitely more extensible.

Have a question about programming in Visual Basic, Visual FoxPro, Microsoft Access, Office or stuff like that? Send your questions via email to George Shepherd at 70023.1000@compuserve.com

From the August 1997 issue of Microsoft Systems Journal. Get it at your local newsstand, or better yet, subscribe.

© 1997 Microsoft Corporation. All rights reserved. Legal Notices.

© 2016 Microsoft Corporation. All rights reserved. Contact Us |Terms of Use |Trademarks |Privacy & Cookies
Microsoft