Let's now look at a basic handler implementation using HCosmo (Cosmo Handler, found in CHAP19\MCOSMO) as an example. This handler is structured the same as any other in-process module, with DllGetClassObject, DllCanUnloadNow, a class factory (these three items are in HCOSMO.CPP), and an object that implements the correct interfaces (FIGURE.CPP). Its REG file contains only two entries; these are meant to modify the entries of Cosmo in Chapter 18. Specifically, HCosmo changes Cosmo's InprocHandler32 key and removes OLEMISC_RECOMPOSEONRESIZE from Cosmo's MiscStatus bits. With a handler we can recompose directly without having to run the local server at all.
HCosmo implements the handler object by using its own version of the class CFigure, matching the class name we used in Chapter 18's Cosmo. This object creates an instance of the default handler during initialization and obtains IOleObject, IViewObject2, IDataObject, and IPersistStorage pointers from it. HCosmo delegates many function calls to these interfaces and directly exposes the default handler's IOleCache2, IOleCacheControl, and IRunnableObject interfaces (from within CFigure::QueryInterface).
HCosmo's purpose in being a handler is to optimize output through IViewObject2::Draw in a minimal sort of way—but in a way that demonstrates the idea nonetheless. To that end, we implement most of IViewObject2 for DVASPECT_CONTENT and DVASPECT_THUMBNAIL, leaving DVASPECT_ICON to the default handler. We implement IOleObject::GetExtent (to call IViewObject2::GetExtent) and IOleObject::DoVerb (to show a message), delegating the remainder of IOleObject to the default handler. We fully implement IPersistStorage as well so we can make copies of the object. In addition, all of the member functions in this interface call the default handler so it can maintain the cache properly. This implementation of IPersistStorage also handles conversion and emulation for Polyline figure data.1
The other interesting part of the CFigure class in HCosmo is that it implements IAdviseSink so that it can receive notifications from Cosmo itself. This interface is not exposed to the container but is connected explicitly to the local object when it becomes a running object. We'll see later why this is important.
1 It does not implement OLE 1 conversion and emulation support, however. |