A Review of ActiveX
Controls
A complete review of the COM interfaces and
interactions between an ActiveX control and a control container is
outside the scope of this book. If you are unfamiliar with the
various interfaces and interactions described in this chapter,
various other texts specifically address these topics. Inside OLE (Microsoft Press, 1995), by Kraig
Brockschmidt, is the original COM text; it devotes hundreds of
pages to in-place activation and visual interface components.
An ActiveX control is a superset of an in-place
activated object, so you also need to read the OLE Controls Specification from Microsoft,
which describes the requirements to be a control. In addition, the
OLE Controls 1996 Specification,
commonly referred to as the OC96 spec, documents optimizations for
control activations (such as windowless controls and windowless
control containment), two-pass rendering for nonrectangular
windows, hit testing for nonrectangular windows, fast-activation
protocols between controls and containers, and numerous other
features.
Instead of rewording the material available in
these references, I show you how to implement such an object. This
chapter describes how to implement a feature-complete ActiveX
control using ATL.
ActiveX Control
Functionality
A control incorporates much of the functionality
you saw in earlier chapters. For example, a control is a COM
object. Therefore, an ATL control contains all the standard
functionality of an ATL-based COM object. A control is a
user-interface (UI) component; therefore, it has thread affinity
and should live in a single-threaded apartment. A control thus
derives from the
CComObjectRootEx<CComSingleThreadModel> base
class.
A control must be a createable class so its
container can instantiate it. Therefore, the control class also
derives from CComCoClass. Many controls use the
CComCoClass default class object's implementation of the
IClassFactory interface. Licensed controls override this
default by specifying the DECLARE_CLASSFACTORY2 macro,
which declares a class object that implements the
IClassFactory2 interface.
In addition, most
controls support one or more of the following features:
-
Stock properties and methods such as
ForeColor and Refresh that a container can access
via the control's IDispatch implementation.
-
Custom properties and methods that a container
can access via the control's IDispatch implementation.
-
Stock and custom event callback methods using
the connection points protocol to a container's
dispinterface implementation. This requires the control to
implement the IConnectionPointContainer and
IProvideClassInfo2 interfaces, as well as a connection
point that makes calls to the event dispinterface.
-
Property change notifications to one or more
clients using the connection points protocol to the clients'
IPropertyNotifySink interface implementations. Control
properties that send such change notifications should be marked in
the control's type library using the bindable or
requestedit attributes, as appropriate.
-
On-demand rendering of a view of the object via
the IViewObject, IView-Object2, and
IViewObjectEx interfaces.
-
Standard OLE control functionality, as provided
by the IOleControl interface, and in-place activation
using the IOleObject and IOleInPlaceActiveObject
interfaces.
-
Persistence support for various containers. At a
minimum, a control typically provides support so that a container
can save the object into a stream using the
IPersistStreamInit interface. Many controls also support
persistence to a property bag using IPersistPropertyBag
because Visual Basic and Internet Explorer prefer this medium. Some
controls additionally support IPersistStorage so that they
can be embedded into OLE documents.
-
Fast and efficient windowless activation, as
provided by the IOleInPlace-ObjectWindowless interface
when the control's container supports this optimization.
-
Fast and efficient exchange of multiple
interfaces during activation between a control and its controls
using the IQuickActivate interface.
-
Object safety settings either through component
category membership or via IObjectSafety.
-
Drag-and-drop support, as provided by
implementations of the IDataObject, IDropSource,
and IDropTarget interfaces.
-
A graphical user interface that provides a means
to edit the control's properties. Typically, a control provides one
or more COM objects, called property
pages, each of which displays a user interface that can
modify a logically related subset of the control's properties. A
container requests the CLSIDs of the property page COM
objects using the control's ISpecifyPropertyPages
interface implementation.
-
A container's capability to
access information about the properties of a control that supports
property pages by using the IPerPropertyBrowsing
interface. For example, the container can obtain a text string
describing a property, determine which property page contains the
user interface to edit the property, and retrieve a list of strings
describing the allowed values for the property.
-
Support for arranging the control's properties
by category in Visual Basic's property view. A control implements
the ICategorizeProperties interface to provide the list of
categories to Visual Basic and to map each property to a
category.
-
Default keyboard handling for an ActiveX
control. This is commonly needed for tabbing, default button
presses on Enter, arrow keys, and pop-up help.
-
MiscStatus flags settings for a
control. Special settings are necessary for some controls to
operate properly.
Property Page
Functionality
Because a control frequently provides one or
more property pages, a complete control implementation also
supplies one or more property page objects, which do the
following:
-
Implement (at least) the IPropertyPage
interface, which provides the main features of a property page
object.
-
Optionally implement the IPropertyPage2
interface to support selection of a specific property. Visual Basic
uses this support to open the correct property page and set the
input focus directly to the specified control when the user wants
to edit a property.
-
Receive property change notifications from one
or more controls using the connection points protocol to the
property page's IPropertyNotifySink interface
implementation.
|