Controls by ATL

[Previous] [Next]

ATL produces six kinds of controls: a full control, a composite control, an HTML control, and lightweight versions of each of these controls—a "lite" full control (which the Object Wizard calls a "lite control"), a "lite" composite control, and a "lite" HTML control. The Microsoft Visual C++ documentation describes in general terms how these controls differ. For example, the documentation says a full control is an object that supports the interfaces for all containers. A lite control supports the interfaces needed by Microsoft Internet Explorer and includes support for a user interface. A composite control consists of a dialog resource hosting a group of regular Microsoft Windows controls. A lite composite control is a composite control that supports only the interfaces Internet Explorer needs. An HTML control is a control that contains DHTML functionality and has an interface generated by an HTML Web page. Finally, a lite HTML control is a stripped-down HTML control that supports interfaces required by Internet Explorer.

Unfortunately, these descriptions don't tell the whole story. So let's take a deeper look at exactly what's going on here. We'll find out what's at the heart of each control.

The Full Control

In the old days of COM (six whole years ago), Microsoft defined a technology named OLE controls. As mentioned earlier, OLE controls were COM classes that implemented a host of interfaces—many of them for supporting the OLE Embedding protocol. For example, if you look at MFC's base class for supporting ActiveX controls (COleControl), you'll see implementations of over twenty COM interfaces.

In 1996, the OC96 protocol emerged. OC96 changed the definition of a COM-based control from one of these gargantuan COM classes that implements a ton of interfaces to a COM class implementing only IUnknown. Microsoft redefined the specification of a control because the size of these executable objects had become a real issue in a browser-centric world. All the classic OLE control interfaces were still valid. They had simply become options. Unfortunately, such a broad definition began to confuse developers.

In addition to the standard OLE control features (embedding, connection points, incoming dispatch interfaces, and so on), the OC96 specification defines such features as delayed activation, windowless controls, hit detection for windowless controls, and quick activation. Most of these features represent optimizations to increase the efficiency and reduce the size of the control.

For example, by employing delayed activation, a control can be instantiated by its container and wait to execute the expensive OLE embedding and activation protocols until the container asks the control to activate. ActiveX controls have historically had their own windows, adding to the instantiation overhead. (The control has to go through the trouble of creating its own window.) As a windowless control, an ActiveX control instead relies on the client's window by communicating with the client through the IOleInPlaceObjectWindowless (on the object site) and IOleInPlaceSiteWindowless (on the client side) interfaces. Finally, the 1996 control specification defines a means for clients to activate controls quickly (in one round-trip rather than several) through the IQuickActivate interface.

A full control is one that implements the entire OLE Embedding protocol as well as all the interfaces necessary for the object to be a control. When you select Full Control from the ATL Object Wizard, ATL gives you a control with the entire embedding and activation protocol added. The Object Wizard generates the following code when asked to create a full control:

 class ATL_NO_VTABLE CFullATLControl:      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<IFullATLControl,         &IID_IFullATLControl, &LIBID_ALLCTLSLib>,     public CComControl<CFullATLControl>,     public IPersistStreamInitImpl<CFullATLControl>,     public IOleControlImpl<CFullATLControl>,     public IOleObjectImpl<CFullATLControl>,     public IOleInPlaceActiveObjectImpl<CFullATLControl>,     public IViewObjectExImpl<CFullATLControl>,     public IOleInPlaceObjectWindowlessImpl<CFullATLControl>,     public IPersistStorageImpl<CFullATLControl>,     public ISpecifyPropertyPagesImpl<CFullATLControl>,     public IQuickActivateImpl<CFullATLControl>,     public IDataObjectImpl<CFullATLControl>,     public IProvideClassInfo2Impl<&CLSID_FullATLControl,          NULL, &LIBID_ALLCTLSLib>,     public CComCoClass<CFullATLControl, &CLSID_FullATLControl> {  BEGIN_COM_MAP(CFullATLControl)     COM_INTERFACE_ENTRY(IFullATLControl)     COM_INTERFACE_ENTRY(IDispatch)     COM_INTERFACE_ENTRY(IViewObjectEx)     COM_INTERFACE_ENTRY(IViewObject2)     COM_INTERFACE_ENTRY(IViewObject)     COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceObject)     COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)     COM_INTERFACE_ENTRY(IOleControl)     COM_INTERFACE_ENTRY(IOleObject)     COM_INTERFACE_ENTRY(IPersistStreamInit)     COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)     COM_INTERFACE_ENTRY(ISpecifyPropertyPages)     COM_INTERFACE_ENTRY(IQuickActivate)     COM_INTERFACE_ENTRY(IPersistStorage)     COM_INTERFACE_ENTRY(IDataObject)     COM_INTERFACE_ENTRY(IProvideClassInfo)     COM_INTERFACE_ENTRY(IProvideClassInfo2) END_COM_MAP()  }; 

This is a full-blown control implementing all the interfaces necessary to house the control in any container (a Web page, a Microsoft Visual Basic form, an MFC dialog box, and so on). Scanning the control's inheritance list and interface map reveals that the control implements IFullATLControl (the default incoming interface generated by the Object Wizard), IDispatch, IViewObjectEx, IViewObject2, IViewObject, IOleInPlaceObjectWindowless, IOleInPlaceObject, IOleWindow, IOleInPlaceObjectWindowless, IOleInPlaceActiveObject, IOleControl, IOleObject, IPersistStream, IPersistStreamInit, ISpecifyPropertyPages, IQuickActivate, IPersistStorage, IDataObject, IProvideClassInfo, and IProvideClassInfo2. (Notice that connection point support isn't in the list. That's something you can easily add.)

The IViewObject…, IOleObject, IOleInPlaceObject, IOleInPlaceActiveObject, IPersistStorage, and IDataObject interfaces represent the OLE Document aspects of the control. The other interfaces support the object as a control. This is a full-blown control that implements the complete OLE Embedding protocol, supports the complete OLE control protocol, supports the container in querying for property pages, can persist to streams and storages, and finally can provide type information to the client on demand.

That's a pretty tall order. Let's take a look at what gets left out when you create a lite control.

The Lite Control

The next option the ATL Object Wizard offers is a lite control. The Object Wizard generates the following code when you select Lite Control:

 class ATL_NO_VTABLE CLiteATLControl :      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<ILiteATLControl,          &IID_ILiteATLControl, &LIBID_ALLCTLSLib>,     public CComControl<CLiteATLControl>,     public IPersistStreamInitImpl<CLiteATLControl>,     public IOleControlImpl<CLiteATLControl>,     public IOleObjectImpl<CLiteATLControl>,     public IOleInPlaceActiveObjectImpl<CLiteATLControl>,     public IViewObjectExImpl<CLiteATLControl>,     public IOleInPlaceObjectWindowlessImpl<CLiteATLControl>,     public CComCoClass<CLiteATLControl, &CLSID_LiteATLControl> {  BEGIN_COM_MAP(CLiteATLControl)     COM_INTERFACE_ENTRY(ILiteATLControl)     COM_INTERFACE_ENTRY(IDispatch)     COM_INTERFACE_ENTRY(IViewObjectEx)     COM_INTERFACE_ENTRY(IViewObject2)     COM_INTERFACE_ENTRY(IViewObject)     COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceObject)     COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)     COM_INTERFACE_ENTRY(IOleControl)     COM_INTERFACE_ENTRY(IOleObject)     COM_INTERFACE_ENTRY(IPersistStreamInit)     COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) END_COM_MAP()  }; 

Notice that the lite control's interface is substantially shorter than that of the full control—it supports all the control-oriented interface implementations but not all the OLE Document interface implementations. The following code illustrates the difference between a full control and a lite control:

      public IPersistStorageImpl<CFullATLControl>,     public ISpecifyPropertyPagesImpl<CFullATLControl>,     public IQuickActivateImpl<CFullATLControl>,     public IDataObjectImpl<CFullATLControl>,     public IProvideClassInfo2Impl<&CLSID_FullATLControl,          NULL, &LIBID_ALLCTLSLib>,  BEGIN_COM_MAP(...)     COM_INTERFACE_ENTRY(ISpecifyPropertyPages)     COM_INTERFACE_ENTRY(IQuickActivate)     COM_INTERFACE_ENTRY(IPersistStorage)     COM_INTERFACE_ENTRY(IDataObject)     COM_INTERFACE_ENTRY(IProvideClassInfo)     COM_INTERFACE_ENTRY(IProvideClassInfo2) END_COM_MAP()  

You can tell from the preceding code that Internet Explorer doesn't require ISpecifyPropertyPages, IQuickActivate, IPersistStorage, IDataObject, IProvideClassInfo, or IProvideClassInfo2.

ISpecifyPropertyPages allows a client (Visual Basic, for example) to interrogate the control for a list of property page GUIDs so that the client can host those pages in its own property dialog. IQuickActivate allows clients to load and initialize controls in a single round-trip. IPersistStorage is part of the whole OLE Embedding protocol and allows objects to persist themselves to a structured storage provided by the client. IDataObject is also part of the OLE Embedding protocol proper and is mainly used to transfer presentations (often in the form of a metafile) between a client and an object that live in different process spaces. Finally, IProvideClassInfo2 gives clients an easy way to get a control's type information.

As it turns out, these interfaces are really there to support a separate design mode (often required by Visual Basic developers), but when developers write controls to send over the Internet, they rarely require this. The size of a bare-bones full control using a Unicode release build is 36,864 bytes. A bare-bones lite control using a Unicode release build is 32,768 bytes. You save about 4000 bytes in overhead alone.

Now let's look at ATL's composite controls.

The Composite Control

An ATL composite control is relatively straightforward. It's an ActiveX control whose presentation space is represented by a dialog box. Over the years, many folks have used this idea to collect several controls together and make it easy to drop the functionality into an application. Up until now, however, they've had to roll everything by hand. The ATL composite control is a COM object that supports all the COM control interfaces and manages a dialog box full of controls as well.

The Object Wizard generates the following code when you select Composite Control:

 class ATL_NO_VTABLE CCompositeATLControl :      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<ICompositeATLControl,          &IID_ICompositeATLControl,         &LIBID_ALLCTLSLib>,     public CComCompositeControl<CCompositeATLControl>,     public IPersistStreamInitImpl<CCompositeATLControl>,     public IOleControlImpl<CCompositeATLControl>,     public IOleObjectImpl<CCompositeATLControl>,     public IOleInPlaceActiveObjectImpl<CCompositeATLControl>,     public IViewObjectExImpl<CCompositeATLControl>,     public IOleInPlaceObjectWindowlessImpl<CCompositeATLControl>,     public IPersistStorageImpl<CCompositeATLControl>,     public ISpecifyPropertyPagesImpl<CCompositeATLControl>,     public IQuickActivateImpl<CCompositeATLControl>,     public IDataObjectImpl<CCompositeATLControl>,     public IProvideClassInfo2Impl<&CLSID_CompositeATLControl,          NULL, &LIBID_ALLCTLSLib>,     public CComCoClass<CCompositeATLControl,         &CLSID_CompositeATLControl> { BEGIN_COM_MAP(CCompositeATLControl)     COM_INTERFACE_ENTRY(ICompositeATLControl)     COM_INTERFACE_ENTRY(IDispatch)     COM_INTERFACE_ENTRY(IViewObjectEx)     COM_INTERFACE_ENTRY(IViewObject2)     COM_INTERFACE_ENTRY(IViewObject)     COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceObject)     COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)     COM_INTERFACE_ENTRY(IOleControl)     COM_INTERFACE_ENTRY(IOleObject)     COM_INTERFACE_ENTRY(IPersistStreamInit)     COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)     COM_INTERFACE_ENTRY(ISpecifyPropertyPages)     COM_INTERFACE_ENTRY(IQuickActivate)     COM_INTERFACE_ENTRY(IPersistStorage)     COM_INTERFACE_ENTRY(IDataObject)     COM_INTERFACE_ENTRY(IProvideClassInfo)     COM_INTERFACE_ENTRY(IProvideClassInfo2) END_COM_MAP() }; 

ATL's composite control implements the same interfaces as the full control. The composite control, however, also manages a bunch of regular Windows controls. Notice that the composite control derives from CComCompositeControl (instead of the plain-vanilla CComControl). CComCompositeControl has all the extra code for managing the control's dialog box.

The Lite Composite Control

A lite composite control is a composite control on a diet. As with a regular composite control, the lite version derives from CComCompositeControl so that it can collect some regular Windows controls in a dialog box and manage that dialog box. The following code shows the inheritance list and interface map for an ATL lite composite control:

 class ATL_NO_VTABLE CLiteCompositeATLControl :      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<ILiteCompositeATLControl,         &IID_ILiteCompositeATLControl,         &LIBID_ALLCTLSLib>,     public CComCompositeControl<CLiteCompositeATLControl>,     public IPersistStreamInitImpl<CLiteCompositeATLControl>,     public IOleControlImpl<CLiteCompositeATLControl>,     public IOleObjectImpl<CLiteCompositeATLControl>,     public IOleInPlaceActiveObjectImpl<CLiteCompositeATLControl>,     public IViewObjectExImpl<CLiteCompositeATLControl>,     public IOleInPlaceObjectWindowlessImpl<CLiteCompositeATLControl>,     public CComCoClass<CLiteCompositeATLControl,         &CLSID_LiteCompositeATLControl> { BEGIN_COM_MAP(CLiteCompositeATLControl)     COM_INTERFACE_ENTRY(ILiteCompositeATLControl)     COM_INTERFACE_ENTRY(IDispatch)     COM_INTERFACE_ENTRY(IViewObjectEx)     COM_INTERFACE_ENTRY(IViewObject2)     COM_INTERFACE_ENTRY(IViewObject)     COM_INTERFACE_ENTRY(IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceObject)     COM_INTERFACE_ENTRY2(IOleWindow, IOleInPlaceObjectWindowless)     COM_INTERFACE_ENTRY(IOleInPlaceActiveObject)     COM_INTERFACE_ENTRY(IOleControl)     COM_INTERFACE_ENTRY(IOleObject)     COM_INTERFACE_ENTRY(IPersistStreamInit)     COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit) END_COM_MAP() }; 

You can see that the difference between the regular composite control and the lite composite control is similar to the difference between ATL's full control and its lite control. The full version supports the design-time interface for property pages and the OLE Embedding protocol, whereas the lite version leaves out these interfaces and this functionality. The regular bare-bones composite control compiles to 45,056 bytes, whereas the bare-bones lite version compiles to 40,960 bytes, saving you about 5000 bytes.

The final type of control ATL supports is the HTML control, which we'll turn to now.

The HTML Control

An HTML control is an ActiveX control that hosts the standard WebBrowser control, specifies its user interface using HTML, and can programmatically access the browser using IWebBrowser2 (implemented by the WebBrowser control). Here's the inheritance list and interface map the Object Wizard generates for a full HTML control:

 class ATL_NO_VTABLE CHTMLATLControl :      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<IHTMLATLControl,          &IID_IHTMLATLControl, &LIBID_ALLCTLSLib>,     public IDispatchImpl<IHTMLATLControlUI,          &IID_IHTMLATLControlUI, &LIBID_ALLCTLSLib>,     public CComControl<CHTMLATLControl>,     public IPersistStreamInitImpl<CHTMLATLControl>,     public IOleControlImpl<CHTMLATLControl>,     public IOleObjectImpl<CHTMLATLControl>,     public IOleInPlaceActiveObjectImpl<CHTMLATLControl>,     public IViewObjectExImpl<CHTMLATLControl>,     public IOleInPlaceObjectWindowlessImpl<CHTMLATLControl>,     public IPersistStorageImpl<CHTMLATLControl>,     public ISpecifyPropertyPagesImpl<CHTMLATLControl>,     public IQuickActivateImpl<CHTMLATLControl>,     public IDataObjectImpl<CHTMLATLControl>,     public IProvideClassInfo2Impl<&CLSID_HTMLATLControl,          NULL, &LIBID_ALLCTLSLib>,     public CComCoClass<CHTMLATLControl, &CLSID_HTMLATLControl> {  }; 

The presentation and user interface for this control are driven by HTML. The HTML source is included in the control's resource. The HTML control loads the HTML into the browser when the control's window is created.

As with the other types of controls, the HTML control also has a stripped-down version, which we'll examine next.

The Lite HTML Control

The lite HTML control has the same functionality as the regular HTML control. The following code shows the inheritance list and interface map the Object Wizard generates for a default lite HTML control:

 class ATL_NO_VTABLE CLiteHTMLATLControl :      public CComObjectRootEx<CComSingleThreadModel>,     public IDispatchImpl<ILiteHTMLATLControl,          &IID_ILiteHTMLATLControl,         &LIBID_ALLCTLSLib>,     public IDispatchImpl<ILiteHTMLATLControlUI,         &IID_ILiteHTMLATLControlUI,         &LIBID_ALLCTLSLib>,     public CComControl<CLiteHTMLATLControl>,     public IPersistStreamInitImpl<CLiteHTMLATLControl>,     public IOleControlImpl<CLiteHTMLATLControl>,     public IOleObjectImpl<CLiteHTMLATLControl>,     public IOleInPlaceActiveObjectImpl<CLiteHTMLATLControl>,     public IViewObjectExImpl<CLiteHTMLATLControl>,     public IOleInPlaceObjectWindowlessImpl<CLiteHTMLATLControl>,     public CComCoClass<CLiteHTMLATLControl,         &CLSID_LiteHTMLATLControl> {  }; 

The lite version of the HTML control simply omits the design-time support. A bare-bones regular HTML clocks in at 40,960 bytes, whereas a lite HTML control clocks in at 36,864 bytes.



Inside Atl
Inside ATL (Programming Languages/C)
ISBN: 1572318589
EAN: 2147483647
Year: 1998
Pages: 127

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net