Step-by-Step Embedding with Local Servers: Cosmo

The remainder of this chapter will follow modifications I've made to Cosmo (CHAP18\COSMO) so that it can now serve embedded objects of CLSID_CosmoFigure. Unlike a container, a server has very little user interface to contend with: instead, most of the work is functional and deals with rendering and exchanging data. In other words, the server has to define how a cookie looks, how it tastes, what kind of ingredients it needs, and how to mix together all those ingredients. It does not, however, have to worry about the cookie jars, counters, kitchens, and houses in which the cookie jars would sit. Its only concerns are the cookies.

Implementing a basic embeddable object and its server involves the following steps:

Initialize and uninitialize OLE on startup and shutdown with OleInitialize and OleUninitialize, as usual.

Create the necessary registry entries for the object and its server, as discussed in Chapter 17.

Implement a class factory for your embedded object class with all the usual shutdown conditions (described in Chapter 5) along with an extra user control flag if necessary.

Implement the object class that will be the embedded object itself.

Implement IPersistStorage on the object, adding necessary conversion and emulation support. Much of this code can use existing functions that read and write your data to IStorage objects if such code already exists.

Implement IDataObject on the object. If you have already written code to handle the clipboard by means of a data object, this implementation will be straightforward and will require only the addition of other OLE formats.

Implement IOleObject on the object, including verb handling. Most of the members in this large interface are easy to implement.

Modify your server's user interface when editing an embedded object to eliminate or disable various menu commands. You should also change the window's caption bar to reflect the embedding state. This also affects your implementation of File Save As and File Close commands.

Send notifications of data change, closure, saving, and renaming at various times in the object's life.

(Full servers) Augment your server's clipboard code to create embedded objects.

(MDI full servers) Provide alternative user interface for MDI applications, which adds another shutdown condition.

We've seen plenty of examples of steps 1, 2, and 3 in previous chapters, so we won't go into detail here about class factories, the registry, and what to do with -Embedding on the command line—for example, not showing the main window until something such as IOleObject::DoVerb(OLEIVERB_SHOW) is called. In this chapter, Cosmo registers its class factory only if -Embedding appears, and it uses REGCLS_SINGLEUSE to avoid some of the complications of an MDI server, as described in step 11. However, because Cosmo is generally an MDI application, it does allow the user to create new documents while Cosmo is otherwise visible to serve an embedded object. In this case, Cosmo sets its user control flag, g_fUser, to TRUE to prevent automatic shutdown when the embedded object is itself closed.

Cosmo's registry entries include a single verb visible to the end user, that being Edit. This is Cosmo's primary verb. In addition, Cosmo marks itself with OLEMISC_CANTLINKINSIDE because we don't deal with monikers yet. (We'll change this in Chapter 21.) The MiscStatus bits for DVASPECT_CONTENT also include OLEMISC_RECOMPOSEONRESIZE so we can see exactly how that works with a container such as Patron. It is interesting to note that the server itself doesn't have to do anything to support this option—the burden is entirely on the container. Whenever Patron resizes a Cosmo object, you'll see a delay in which Cosmo is launched and asked to render the object before being asked to close. Cosmo never becomes visible to the user through this sequence.

Cosmo also registers itself as capable of both converting and emulating the Polyline objects from Chapter 19's Polyline sample (the "Polyline Figure" format) and those from Cosmo's old OLE 1 version (ProgID of "Cosmo1.0"). You can find the source for this version of Cosmo in CHAP18\COSMO1.0. A discussion of what's involved is included in OLE1.WRI on the companion CD.