Click to return to the Component Development home page    
Web Workshop  |  Component Development

Design-time Control Host Services


Updated: July 15, 1996

Summary

Hosts can provide a variety of services for design-time controls to use. Services are a convenient means of getting access to features implemented by the site. This document covers the following topics you need to understand if your design-time control will use services:

Contents
The Service Architecture
Service Definitions
Using Services
Visual InterDev Services for C++
WebDesignControlContext Service
BuilderWizardManager Service
Visual InterDev Services for Visual Basic
DBConnections Collection
DBConnection Object
WebDesignControlContext Service Object



The Service Architecture

A service is a group of related interfaces that perform a task, such as finding the code attached to an object or displaying help. A host provides services to ensure that these tasks are accomplished in a uniform way across its contained objects.

ActiveX™ designers access services through their site. 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.

Siting and Containers

A container communicates with the ActiveX controls and designers it contains through a site. A site is a class implemented by the container. There is one site for each contained object. The site acts as an intermediary between the container and the object. When an ActiveX designer requires the use of a method or property of its container, it requests the feature through its site. This design lets the container know which object is making the request.

The site implements the IOleClientSite interface (or the IOleControlSite interface, if it contains ActiveX controls), and the ActiveX designer implements the IOleObject interface, as in the following figure.

[abdes028  2631 bytes ]

At design time, the site calls IOleObject::SetClientSite, which gives the ActiveX designer a pointer to the site. Through this pointer, the ActiveX designer can use the site's IDispatch interface to change ambient properties.

Although the site provides useful information to the container about what the designer and other contained objects are doing, siting makes interactions indirect. To use interfaces implemented by the container, the ActiveX designer must issue requests through the site. Services provide an efficient architecture for locating and using these interfaces.

Providing Services through a Site

Services are groups of related interfaces. Typically, a service is defined for actions that are performed by a site. The service itself is defined by the site, but the interfaces that make up the service may be implemented by other objects on the site.

The service architecture provides a flexible, general means of making features accessable to contained objects. The flexibility comes from several important aspects of the design:

The following figureshows a hypothetical service implementation.

[abdes029  2847 bytes ]

The figure shows four interfaces. The IServiceProvider interface provides access to services. All sites that support services implement this interface. ActiveX designers and other contained objects call the QueryService method of IServiceProvider to get pointers to the interfaces they want to use.

The other three interfaces illustrate hypothetical service implementations. The table shows the various combinations of services that can be defined. Each service has a unique service identifier (SID), similar to an interface identifier (IID). The SID is a globally unique identifier (GUID) that identifies the service in calls to QueryService.

Service Service and Interface Identifiers Description
Montana service SID_SMontana Provides access to the Montana interfaces.
  IID_IMontana Montana interface.
Washington service SID_SWashington Provides access to the Washington interfaces.
  IID_IWashington Original Washington interface.
Washington2 service SID_SWashington2 Second version of the Washington service.
  IID_IWashington Original Washington interface. Same as IID_IWashington in SID_SWashington.
  IID_IWashington2 Second version of the Washington interface, with different features.

In the figure, the Montana service is implemented on the site object and the two Washington services are implemented on a separate object. The following configurations are also possible:

Because the IWashington interface is the same in both SWashington and SWashington2, both of these services can be implemented on the same object.

This design allows ActiveX designers and other embedded objects straightforward access to useful features of their containers. The container, in turn, can configure these features efficiently. All configurations are transparent to the ActiveX designer, and different containers may organize the services differently.

Services, Interfaces, and Object Identity

QueryService identifies an object that supports the requested service, with the returned pointer already set to the specified interface.

It's important to keep in mind the following:

Two different services (SID_SIdaho and SID_SMontana, for example) can both specify the use of a single interface (for example, IDispatch), even though the implementation of the interface may have nothing in common between the two services. This works because the following two hypothetical calls can return different objects:

hr = QueryService (SID_SMontana, IID_IDispatch, &pDisp) 
hr = QueryService (SID_SIdaho, IID_IDispatch, &pDisp)

Remember that object identity is not assumed if you ask for a different service identifier.

TopBack to top

Service Definitions

Services useful for ActiveX™ designers are defined in the Designer.h header file provided by Microsoft. The following code, taken from Designer.h, defines the SCodeNavigate service, which allows an extended object to display the code module attached to it.

// { 6d5140c4-7436-11ce-8034-00aa006009fa }
DEFINE_GUID(IID_ICodeNavigate, 0x6d5140c4, 0x7436, 0x11ce, 0x80, 0x34, 
0x00, 0xaa, 0x00, 0x60, 0x09, 0xfa);
#define SID_SCodeNavigate IID_ICodeNavigate

#undef  INTERFACE
#define INTERFACE  ICodeNavigate
DECLARE_INTERFACE_(ICodeNavigate, IUnknown)
{
    BEGIN_INTERFACE
    // *** IUnknown methods ***
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) 
         PURE;
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    STDMETHOD_(ULONG, Release)(THIS) PURE;

    // *** ICodeNavigate methods ***
    STDMETHOD(DisplayDefaultEventHandler)(
                     THIS_ /* [in] */ LPCOLESTR lpstrObjectName
                     ) PURE;
};

Every service is associated with an SID. Components that need to use a service pass the SID to IServiceProvider::QueryService. In the example, the SID for SCodeNavigate is SID_SCodeNavigate. Often, the SID is the same as the IID for one of the interfaces that belongs to the service. Here, SID_SCodeNavigate is defined to equal IID_ICodeNavigate.

The service includes the standard IUnknown interface and one or more additional interfaces. In the example, only one additional interface, ICodeNavigate, is defined. This interface contains one method, DisplayDefaultEventHandler.

TopBack to top

Using Services

Services provide several important advantages for ActiveX™ designers:

The following sections describe how to find and call services, and what the differences are between using services and using the QueryInterface method.

Finding a Service

To locate a service, an ActiveX designer calls the IServiceProvider interface, implemented by its site. The interface has the following definition:

interface IServiceProvider : IUnknown
{
   HRESULT QueryService ( REFGUID rsid, REFIID iid, void ** ppvObj) 
};

The input parameters to the QueryService method are the SID of the service being requested and the IID of the interface you want to use. In return, you receive a pointer to the requested interface if the host implements the service, or E_NOTIMPL if the host does not implement it.

For example, the following code fragment queries for the SCodeNavigate service. (Error handling has been omitted for brevity.)

hr = pClientSite->QueryInterface(IID_IServiceProvider, &pISP); 
hr = pISP->QueryService(SID_SCodeNavigate, IID_ICodeNavigate, &pICN);

The example calls QueryInterface on the site to get a pointer to the site's IServiceProvider interface. Using the returned pointer, it passes the SID of the SCodeNavigate service and the IID of the ICodeNavigate interface to QueryService. If the call is successful, QueryService returns a pointer to the ICodeNavigate interface. Through this pointer, the ActiveX designer can invoke the methods defined for ICodeNavigate.

In effect, the site performs the equivalent of the following for each call to QueryService:

pSite->QueryService (SID_SCodeNavigate, IID_IUnknown, &pUnk);
pUnk->QueryInterface (IID_ICodeNavigate, &pICN);
pUnk->Release();

The ActiveX designer receives a pointer through which it can directly access the requested interface. The site does not have to delegate each individual method call.

Calling a Service

After it has called QueryService to get a pointer to an interface that is part of a service, an ActiveX designer can simply call the interface through the pointer. For example, the following two lines of code get a pointer to the ICodeNavigate interface in the SCodeNavigate service, as described in the preceding section:

hr = pClientSite->QueryInterface(IID_IServiceProvider, &pISP); 
hr = pISP->QueryService(SID_SCodeNavigate, IID_ICodeNavigate, &pICN);

Assuming that the QueryService call returns without error, the following code fragment calls the DisplayDefaultEventHandler method of ICodeNavigate:

hr = pICN->DisplayDefaultEventHandler(lpMyObject);

Typically called in response to an event such as a mouse-click this method displays the default event handler for the object named in lpMyObject.

Differences between QueryService and QueryInterface

Although it might seem logical to call QueryInterface to find the interface you want to use, services are a more efficient means of getting the same capabilities.

The key difference between the QueryService and QueryInterface methods is that QueryInterface on an object returns an interface on the same object, whereas QueryService makes no such guarantee. QueryService on an object may return an interface on the same object or on a different object.

Because services need not be implemented on the site object, calling QueryInterface on the site to look for interfaces in a service is not guaranteed to succeed.

In addition, calling QueryInterface on an object you receive from QueryService is valid only for interfaces that are part of the service. Querying for any other interfaces results in an error status.

TopBack to top

Visual InterDev Services for C++

Currently, design-time controls in Microsoft® Visual InterDev™ may use the services listed in the following table. This service are accessable from Microsoft® C++ and from Microsoft® Visual Basic®. The services are exposed to Visual Basic using a special helper API that is part of the SDK. The helper API and the Service object it returns are documented below. These services are defined in the header file Designer.h.

Service Interfaces Purpose
SApplicationObject IDispatch Returns the programmability interface for the host's add-in model.
SWebDesignControlContext IDispatch Returns an object which provides design-time control context information.
SBuilderWizardManager IBuilderWizardManager Returns an interface for retrieving builders.

ApplicationObject Service

The SApplicationObject service provides access to a pointer to the host's add-in model. The add-in model is the top-level Application object, an Automation object that designers, wizards, and add-ins can use. Not all hosts implement this service, and different hosts define the add-in model differently. Refer to your host documentation for more information.

You can query the service for the IDispatch and IUnknown interfaces. For information on these interfaces, see the Automation Programmer's Reference.

The service identifier (SID) for this service is SID_SApplicationObject.

How to Get to Project Data Connections

Access to project data connections is done using the Application object returned by the ApplicationObject service. The ActiveProject property on the application object returns an IDispatch pointer for the active project. The DBConnections property on the active project object returns an IDispatch pointer for the collection of project data connections. Refer to the documentation on DBConnections and DBConnection in the Visual Basic section.

TopBack to top

WebDesignControlContext Service

ServerLanguage Property

Retrieves the server language string from the Active Server Page file containing the control.

Comments

ServerLanguage is a read-only property that contains the string representing the current server language setting. This is determined by scanning the current file for the Active Server script language tag. If this tag does not exist, the default language is "VBScript." This setting can be used to adjust the script produced when providing run-time text during persistence. To use this property, use the IServiceProvider interface to query for the SID_SWebDesignControlContext service and request an IDispatch interface. Use GetIDsOfNames to retrieve the DISPID of the "ServerLanguage" property and then request the property value which will be a BSTR containing the server language string.

TopBack to top

BuilderWizardManager Service

This is a more complex service that is documented in Invoking Builders and Wizards. Here we are listing methods specific to builders that can be invoked inside Microsoft® Visual InterDev™.

URLPicker.Execute Method

Invokes the URL Picker dialog box. The URL Picker is a builder that can be requested using IBuilderWizardManager.


HRESULT Execute(
   IDispatch* pdispAppObject,
   HWND hwndOwner,
   IServiceProvider* pspProvider,
   VARIANT* pvarURL
   LPCTSTR pszBaseURL,
   LPCTSTR pszAdditionalFilters,
   LPCTSTR pszcDlgTitle,
   VARIANT* pvarTargetFrame,
   long* pdwFlags,
   VARIANT_BOOL* pbRet
);

Parameters

Return Values

The return value obtained from HRESULT is one of the following:

Return value Meaning
S_OK Success.
E_INVALIDARG One or more of the arguments is invalid.
E_FAIL The dialog box could not be created.

Comments

The Execute method invokes the URL Picker dialog box, which allows the user to select a file in the project and generate the associated URL. You must first retrieve a pointer to the URL Picker's IDispatch interface by using the IBuilderWizardManager interface. Pass CATID_URLBuilder as the builder category. Once you have the IDispatch interface, retrieve the DISPID of the "Execute" method by calling GetIDsOfNames. Once the dialog box is dismissed, the pvarURL parameter containing the selected URL.

The pdwFlags parameter can contain one or more of the following values:

#define URLP_SHOWTARGETFRAME      0x0001   // show target frame edit control
// The following 3 are mutually exclusive
#define URLP_CREATEURLTITLE       0x0002   // use "Create URL" title for dialog
#define URLP_EDITURLTITLE         0x0004   // use "Edit URL" title for dialog
#define URLP_CUSTOMTITLE          0x0008   // use custom title specified by user

// The following 3 are mutually exclusive
#define URLP_DOCRELATIVEURLTYPE   0x0010   // return doc relative URL
#define URLP_ROOTRELATIVEURLTYPE  0x0020   // return root relative URL
#define URLP_ABSOLUTEURLTYPE      0x0040   // return absolute URL

// Make sure that these do not clash with the flag above
// Any of the following two can be specified with a logical 'OR'
// These flags determine the options available in the URL type combo box
#define URLP_DISALLOWDOCRELATIVEURLTYPE  0x0080   // do not show "Doc Relative"
#define URLP_DISALLOWROOTRELATIVEURLTYPE 0x0100   // do not show "Root Relative"
#define URLP_DISALLOWABSOLUTEURLTYPE     0x0200   // do not show "Absolute"

GetService Helper Function

The GetService function can be used to retrieve the VIService object, which is implemented by the VBIServ.dll helper library. This object provides methods for invoking the Query Builder and for retrieving the ODBC handle from a connection. Call GetService passing the pointer to your control in a VARIANT as the first parameter and STR_VIService as the second parameter. The third parameter should be initialized with a reference to an IDispatch pointer that will hold the returned service object.

BOOL GetService(
   VARIANT* pvarObject,
   char* pszGuid,
   VARIANT* pvarService
) ;

Parameters

Return Values

True if the function is successful.

Comments

GetService returns a service object based on the GUID string that's passed in. This provides a way for a control to access services provided by the host. Specific services provided by Visual InterDev are documented elsewhere in this document.

VIService Service Object

This service object can be retrieved by using the GetService function and passing STR_VIService as the GUID string. It provides methods for invoking the Query Builder and retrieving the ODBC handle from a connection. This is an IDispatch object. Refer to the section titled Visual InterDev Services for Visual Basic for more information about the methods available on this object.

TopBack to top

Visual InterDev Services for Visual Basic

Visual Basic 5.0 Programmers

To make life simpler for the Microsoft Visual Basic programmer, we have provided a helper function that returns a VIService object. This object has methods that provide access to all of Microsoft Visual InterDev's services. The Data Grid sample control included in the SDK shows this in action. In the following descriptions, a service is just an object.

GetService Helper Function

Retrieves a service from the host based on a GUID string. The function declaration and GUIDs for the different services are in the vbiserv.bas found in the common directory in the VB samples directory.

Public Function GetService(
   vControl as Variant,
   strGuid as String
   oService as Variant
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

GetService returns a service object based on the GUID string that's passed in. This provides a way for a control to access services provided by the host. Specific services provided by Visual InterDev are documented elsewhere in this document.

VIService Service Object

This service object is returned by the GetService function call and lets you work with builders and data connections.

GetBuilder Method

Retrieves a builder object associated with a specific GUID.

Public Function GetBuilder(
   strGUID as String,
   oAppObject as Object,
   lOwnerWindow as Long,
   oBuilder as Object
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

The GetBuilder method retrieves the builder object associated with a specific GUID. Each builder will have a different method of invocation. Refer to the documentation for the specific builder you're using for information on how to invoke it.

GetDBConnections Method

Retrieves an object containing the list of data connections currently available. See later section for methods and properties for the DBConnections collection.

Public Function GetDBConnections(
   oConnections as DBConnections
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

The GetDBConnections method retrieves an object that contains a list of the data connections currently available. This connection collection is documented under DBConnections above.

GetConnectionHandle Method

Retrieves an ODBC handle for a specific data connection.

Public Function GetConnectionHandle(
   oConnection as DBConnection,
   hConnection as Long
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

The GetConnectionHandle method retrieves an ODBC handle from a DBConnection object. This handle can be used with various ODBC driver calls to work directly with the connection. This makes it possible to do such things as query the connection for a list of tables or execute a query on the connection. When you're done with the connection handle, you must call ReleaseConnectionHandle on the same connection object.

ReleaseConnectionHandle Method

Releases the ODBC handle for a specific data connection.

Public Function ReleaseConnectionHandle(
   oConnection as DBConnection
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

The ReleaseConnectionHandle method releases the ODBC handle previously obtained from a call to GetConnectionHandle. Once this call is complete, the connection handle is no longer valid.

CallSQLBuilder Method

Invokes the SQL Query Builder. The SQL Builder included in Visual InterDev is implemented as a special builder with its own service for getting to it.

Public Function CallSQLBuilder(
   oControl as Object,
   oConnection as Object,
   strOwnerName as String,
   strPropertyName as String
) as Boolean;

Parameters

Return Values

True if the function is successful.

Comments

The CallSQLBuilder method invokes the SQL Query Builder, which allows the user to visually create an SQL statement. When the user is through, the resulting SQL statement is stored in the property that is named by the fourth parameter.

TopBack to top

DBConnections Collection

This collection will give you access to the project data connections.

Add Method

Adds a new data connection to the project.

Public Function Add(
   strDataSourceName as String,
   strConnectString as String
) as DBConnection;

Parameters

Return Values

A DBConnection object.

Comments

Adds a new data connection to the project. The sConnectionString can optionally include Server, UserID, and Password. If the DataSourceName is null, then one will be generated. If the ConnectionString is null, a new connection will be created and the ODBC Service will generate this string. If the complete ConnectString is not specified, then the ODBC Dialog will be presented to collect the missing information.

Item Method

Returns an item from the connection list.

Public Function Item(
   varItem as Variant,
) as Variant;

Parameters

Return Values

A DBConnection object.

Comments

Used to return a unique database connection from the database connection collection either by ID or by name.

Remove Method

Removes a connection from the connection list.

Public Sub Remove(
   varItem as Variant,
);

Parameters

Return Values

Success or trappable run-time error.

Comments

Used to remove a database connection from the database connection collection.

Cleanup Method

Calls the cleanup method on each DBConnection in the connection list.

Public Sub Cleanup();

Return Values

Success or trappable run-time error.

Count Property

The number of database connections in the project.

Public Property Count() as long;

TopBack to top

DBConnection Object

Connect Method

Establishes a database connection in the project or if the "Connected" property is false, attempts to re-connect to data source.

Public Sub Connect();

Return Values

Success or trappable run-time error.

Name Property

Contains the name of the ODBC Connection in the Project.

Public Property Name(strName as String) as String;

Parameters

Return Values

The Database Connection String (Display Name).

Parent Property

Returns the collection of project data connections.

Public Property Parent() as DBConnections;

Return Values

A pointer to the CDBConnections Collection Object.

ConnectionString Property

Contains the complete text of the ODBC Database Connection String.

Public Property ConnectionString(strConnect as String) as String;

Parameters

Return Values

A String value representing the ODBC ConnectString.

ConnectionTimeout Property

Contains the timeout interval in seconds to wait for a connection to the ODBC device to take place.

Public Property ConnectionTimeout(lngTimeOut as Long) as Long;

Parameters

Return Values

The command timeout interval in seconds.

Connected Property

Indicates whether the connection is connected to the data source.

Public Property Connected() as Boolean;

Return Values

A Boolean indicating whether the connection is currently connected.

RuntimeUser Property

Contains the Run-time User Name that will be used for anonymous connections.

Public Property RuntimeUser(strUserName as String) as String;

Parameters

Return Values

The run-time user name that will be used for this data connection.

RuntimePassword Property

Contains the Run-time User Password that will be used for anonymous connections.

Public Property RuntimePassword(strPassword as String) as String;

Parameters

Return Values

The run-time user password that will be used for this data connection.

RuntimeCursorLocation Property

Contains the location where the data connection cursor will reside. Either Zero (default) for the Client or One for Server.

Public Property RuntimeCursorLocation(lngCursorLocation as Long) as Long;

Parameters

Return Values

The run-time user's preferred cursor location.

TopBack to top

WebDesignControlContext Service Object

ServerLanguage Property

Retrieves the server language string from the Active Server Page file containing the control.

Public Property ServerLanguage() as String;

Comments

ServerLanguage is a read-only property that contains the string representing the current server language setting. This is determined by scanning the current file for the Active Server script language tag. If this tag does not exist, the default language is "VBScript." This setting can be used as an indicator of which script language should be produced when generating run-time text. To use this property, call GetBuilder and pass ControlContextGuid as the GUID string. This returns an object which exposes the ServerLanguage property.



Back to topBack to top

Did you find this material useful? Gripes? Compliments? Suggestions for other articles? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.