Export (0) Print
Expand All

Introduction to ActiveX Control Containers

This article is an overview for Microsoft ActiveX control containers. The following sections explain how to implement and program ActiveX control containers that will function well with other controls and containers.

Introduction

An ActiveX control container supplies an environment in which an ActiveX control can run. Additionally, control containers manipulate, manage, and provide services to all the controls they contain. For example, containers supply controls with event handlers and deal with properties. At a minimum, a container must be able to host an ActiveX control. Additionally, it may support component categories, which are sets of interfaces grouped into areas of functionality and assigned a GUID. For example, data binding is a component category. A container may or may not support data binding depending on the needs of its ActiveX control. If a control needs data binding support from a container, the control enters this requirement in the registry. By using the registry information, the container offers for insertion only those controls that it can support.

ActiveX controls have become the primary architecture for developing software components for use in a variety of containers. For a control to operate well in different containers, it must be able to rely on a minimum level of container functionality.

ActiveX control containers must provide support for the following:

  • Embedded objects from in-process servers
  • In-place activation
  • Event handling
  • The OLEMISC_ACTIVATEWHENVISIBLE status bit of the OLEMISC enumeration

Container Requirements

This section addresses the requirements for interfaces, methods, status bits, and special features of ActiveX control containers.

Required and Optional Interfaces

Specific interfaces are used to program ActiveX control containers. The following table lists those interfaces and shows which are optional and which are mandatory.

Interface Support Comments
IAdviseSink Optional This interface is required only when the container requires notifications, such as data change notifications from controls with IDataObject, view change notifications from controls that are not active and have IViewObject2, and other notifications from controls acting as standard embedded objects.
IClassFactory2 Optional This interface is not required but supporting it is recommended.
IDispatch for ambient properties Required
IErrorInfo Required IErrorInfo is mandatory if a container supports dual interfaces.
IOleClientSite Required
IOleContainer Required IOleContainer is implemented on the document or form object that holds the container sites. Controls use the IOleContainer to navigate to other controls in the same document or form.
IOleControlSite Required
IOleInPlaceFrame Required
IOleInPlaceSite Required
IPropertyNotifySink Optional This interface is only needed for containers that have their own property-editing UI.
ISimpleFrameSite Optional This interface, as well as support for nested simple frames is optional.

Not Required and Optional Methods

An ActiveX control container can implement an interface without implementing every method in the interface. For methods that are not mandatory the container may simply return E_NOTIMPL, S_FALSE, or S_OK, as appropriate. There are two types of nonmandatory methods; not required and optional. Methods that are not required do not need to be implemented. Optional methods must be implemented but may return E_NOTIMPL.

The following table identifies and describes the not required and optional methods. Except for the methods listed in the table, all methods from the required ActiveX control container interfaces must be implemented and cannot return E_NOTIMPL.

Interface Method Comments
IDispatch for ambient properties GetIDsOfNames Not required. This method is necessary only for containers that support nonstandard ambient properties.
GetTypeInfo Not required. This method is necessary only for containers that support nonstandard ambient properties.
GetTypeInfoCount Not required. This method is necessary only for containers that support nonstandard ambient properties.
IDispatch for an event sink GetIDsOfNames Not required. This method is not necessary for an event sink.
GetTypeInfo Not required. This method is not necessary for an event sink.
GetTypeInfoCount Not required. This method is not necessary for an event sink.
IOleClientSite GetMoniker Not required. This method is necessary only if the container supports linking to controls within its own form or document.
SaveObject Not required. This method is necessary only if persistence is supported.
IOleContainer EnumObjects Not required. This method is only necessary to enumerate ActiveX controls.
LockContainer Not required. This method is only necessary for containers that link to controls or other embedded objects.
ParseDisplayName Not required. This method is only necessary for containers that link to controls or other embedded objects.
IOleControlSite GetExtendedControl Not required. This method is only necessary for containers that support extended controls.
LockInPlaceActive Optional
ShowPropertyFrame Not required. This method is necessary only for containers that want to include their own property pages to handle extended control properties in addition to those provided by a control.
TranslateAccelerator Not required. This method can return S_FALSE and perform no action.
IOleInPlaceFrame ContextSensitiveHelp Optional
EnableModeless Optional
GetBorder Not required. This method is necessary only for containers with toolbar UI.
InsertMenus Not required. This method is necessary only for containers with menu UI.
RemoveMenus Not required. This method is necessary only for containers with menu UI.
RequestBorderSpace Not required. This method is necessary only for containers with toolbar UI.
SetBorderSpace Not required. This method is necessary only for containers with toolbar UI.
SetMenus Not required. This method is necessary only for containers with menu UI.
SetStatusText Not required. This method is necessary only for containers that have a status line.
TranslateAccelerator Optional
IOleInPlaceSite ContextSensitiveHelp Optional
DeactivateAndUndo Not required. This method must implement deactivation, but undo is optional.
DiscardUndoState Not required. This method can return S_OK and perform no action.
Scroll Not required. This method can return S_FALSE and perform no action.

Status Bit Support

ActiveX control containers must also recognize and support certain status bits of the OLEMISC enumeration. The following table shows which of the OLEMISC status bits are required and which are optional.

Status bit Support Comments
ACTIVATEWHENVISIBLE Required
IGNOREACTIVATEWHENVISIBLE Optional This bit is set for containers hosting inactive and windowless controls.
INSIDEOUT Optional
INVISIBLEATRUNTIME Required This bit designates a control that should be visible at design time, but invisible at run time.
ALWAYSRUN Required
ACTSLIKEBUTTON Optional Support for this bit is normally required, although it is not necessary for document-style containers.
ACTSLIKELABEL Optional Support for this bit is normally required, although it is not necessary for document-style containers.
NOUIACTIVATE Required
ALIGNABLE Optional
SIMPLEFRAME Optional
SETCLIENTSITEFIRST Optional Support for this bit is recommended but is not required.
SIMPLEFRAME Optional
IMEMODE Optional

Requirements for Special Features

In addition to the mandatory interfaces, methods, and status bits, special features like keyboard handling and automatic clipping require certain functionalities for implementation. The following table lists some special feature requirements.

Feature Requirements
Keyboard Handling The following are required for a container to support a keyboard:

  • Support for the OLEMISC status bits OLEMISC_ACTSLIKELABEL and OLEMISC_ACTSLIKEBUTTON.
  • Implementation of the DisplayAsDefault ambient property (if it exists, it can return FALSE).
  • Implementation of tab handling, including tab order.
Storage Interfaces Containers must be able to support controls that implement IPersistStorage, IPersistStream, or IPersistStreamInit. Optionally, a container can support any other persistence interface, such as IPersistMemory, IPersistPropertyBag, and IPersistMoniker.

After an ActiveX control container has selected and initialized a storage interface, the storage interface will remain the primary storage interface for the life of the control. This does not preclude the container from saving to other storage interfaces.

ActiveX control containers are not required to support IPersistPropertyBag and IPropertyBag because the "save as text" mechanism is not required.

Ambient Properties At a minimum, ActiveX control containers must support the following ambient properties using the standard DISPIDs.
  • LocaleID (DISPID = -705): This property is necessary if the locale is significant to the container—for example, for formatting text output.
  • UserMode (DISPID = -709): This property is necessary for containers that have different user and run environments.
  • DisplayAsDefault (DISPID = -713): This property is necessary for containers that have a default button.
Extended Controls ActiveX control containers are not required to support extended controls. However, if the container does support extended controls, it must support the following:
  • Visible
  • Parent
  • Default
  • Cancel
Message Reflection ActiveX control containers are not required to support message reflection. Message reflection is the ability of a subclassed control to handle notification messages itself, rather than have them handled by the container.

Using controls that can handle their own messages results in more efficient controls. If a container supports message reflection, the MessageReflect ambient property must be supported and set to TRUE.

Automatic Clipping ActiveX control containers are not required to support automatic clipping. Automatic clipping is the ability of a container to ensure that a control's visual output goes only to the container's current clipping region.

Using containers that support automatic clipping results in more efficient controls because a control can paint without regard to its clipping region. The container will automatically clip any painting that occurs outside the control's area. If a container supports automatic clipping, the AutoClip property must be supported and set to TRUE.

Degrading When an Interface Is Not Supported

All controls do not support all interfaces. In fact, there are controls that support only the IUnknown interface. When a container encounters a control that does not support a required interface, the container must degrade.

Unsupported Interfaces

The following table describes what a container might do in the absence of a particular interface. Note that the table lists only those interfaces that a container can obtain through QueryInterface.

Interface Comments
IViewObject2 If the IViewObject2 interface is unsupported, a control has no extents and at run time draws nothing. At design time, the container draws a default rectangle, so a user in a visual programming environment can select the object and check its properties, methods, and events. Your application should be prepared to handle the lack of a visual control.
IOleObject Any information, such as control extents, that a container might expect from this interface should be filled in with container-provided defaults.
IOleInPlaceObject If this interface is absent, the control does not attempt to activate in-place. Therefore no handling is required.
IOleControl In the absence of this interface, the container does not call its members.
IDataObject The control provides no property sets or visual renderings that can be cached, so in the absence of this interface the container should cache some default data.
IDispatch The control has no custom properties or methods. Therefore the container does not need to show any control properties and should not allow any custom method calls.
IConnectionPointContainer The control has no events, so the container does not have to handle events.
IProvideClassInfo2 If this interface is missing, the control either does not have type information or events, or the container must obtain the control's type information from the control's registry entries.
ISpecifyPropertyPages The control has no property pages. Therefore if the container has any UI that invokes property pages, the container should disable the UI.
IPerPropertyBrowsing The control has no display name, no predetermined strings and values, and no property-to-page mapping. This interface is used to generate a container user interface. Therefore in the absence of this interface, UI elements should be disabled.
IPersist* Objects The control has no persistent state, so the container does not have to save any control-specific data.
IOleCache2 The control does not support caching.

Programming Considerations

This section describes some guidelines for ActiveX control and ActiveX control container developers.

Programming Guidelines

The following table offers programming suggestions to produce more reliable and interoperable components.

Topic Comments
Overloading IPropertyNotifySink Many ActiveX control containers implement a modeless property browsing window. If a control's properties are altered through the control's property pages, the control's properties can get out of sync with the container's view of those properties. To ensure that a container always has the current values for a control's properties, an ActiveX control container can overload the IPropertyNotifySink interface and use it to notify the container that a control property has changed.
Container-Specific private interfaces Some containers provide container-specific private interfaces for additional functionality or improved performance. Controls that rely on container-specific interfaces should, if possible, work without those interfaces so that the control will function in different containers. For example, Microsoft Visual Basic implements private interfaces that provide string formatting functionality to controls. If a control makes use of those private interfaces, it should be able to run with default formatting support if the interfaces are not available.
Multithreaded issues ActiveX provides support for multithreaded applications, allowing applications to make ActiveX calls from multiple threads. This multithreaded support is called the apartment model. It is important that all ActiveX components using multiple threads follow this model. For more information about apartment model threading, refer to the Windows Software Development Kit (SDK) documentation.
Event freezing A container can notify a control that it is not ready to respond to events by calling IOleControl::FreezeEvents(TRUE). When a container freezes events, it is freezing event processing, not event receiving. A container can still receive events while events are frozen. If a container receives an event notification while its events are frozen, the container should ignore the event. If it is important for a control to process an event, the control should take note of an IOleControl::FreezeEvents(TRUE) call. While a container's event processing is frozen, a control should implement one of the following techniques:
  • Fire the events knowing that the container will take no action.
  • Discard all events that the control would fire.
  • Queue up all pending events and fire them after the container calls IOleControl::FreezeEvents(FALSE).
  • Queue up only relevant or important events and fire them after the container calls IOleControl::FreezeEvents(FALSE).
WS_GROUP and WS_TABSTOP flags in controls A control should not use the WS_GROUP and WS_TABSTOP flags internally. Some containers rely on these flags to manage keyboard handling.
Multiple controls in one DLL A single .ocx DLL can contain any number of ActiveX controls, simplifying the distribution and use of a set of related controls. If you ship multiple controls in a single DLL, be sure to include the vendor name in each control name. Including the vendor's name in each control enables users to easily identify controls within a package. For example, if you ship a DLL that implements three controls, Con1, Con2, and Con3, the control names should be:

<Your company name> Con1 Control
<Your company name> Con2 Control
<Your company name> Con3 Control
IOleContainer::EnumObjects This method is used to enumerate all the OLE objects contained in a document or form, returning an interface pointer for each object. The container must return pointers to each ActiveX object that shares the same container. Nested forms or nested controls must also be enumerated.

Some containers implement extender controls, which wrap non-ActiveX controls, and then return a pointer to these extender controls as a form is enumerated. This behavior enables ActiveX controls and ActiveX control containers to integrate well with non-ActiveX controls.

Enhanced metafile Enhanced metafiles provide more functionality than standard metafiles. Using enhanced metafiles generally simplifies rendering code. An enhanced metafile device context (DC) is used in exactly the same way as a standard metafile DC. A 32-bit ActiveX control container should use enhanced metafiles, but 16-bit containers must use standard metafiles. ActiveX supports enhanced metafiles and includes backward compatibility with standard metafiles.
Licensing In order to embed licensed controls successfully, ActiveX control containers must use IClassFactory2 instead of IClassFactory. Several ActiveX creation and loading helper functions, such as OleLoad and CoCreateInstance, call IClassFactory and not IClassFactory2, and therefore cannot be used to create or load licensed ActiveX controls.
Dual interfaces OLE automation enables an object to expose a set of methods in two ways: through the IDispatch interface and through direct OLE Vtable binding. IDispatch offers late binding support, but Vtable binding offers performance gain. Both techniques are valuable and important in different scenarios. By labeling an interface as "dual" in the type library, an OLE Automation interface can be used through IDispatch or it can be bound to directly.
IPropertyBag and IPersistPropertyBag ActiveX control containers that implement a "save as text" mechanism should use IPropertyBag and IPersistPropertyBag. IPropertyBag is implemented by a container and is roughly analogous to IStream. IPersistPropertyBag is implemented by controls, and is roughly analogous to IPersistStream.

Related Topics

Community Additions

ADD
Show:
© 2014 Microsoft