IDataObject as a Standard for Object Data Transfer

As I mentioned, IDataObject is the standardized interface for data exchange. It makes sense for any object capable of performing any type of data transfer to do as much as it can through IDataObject instead of through custom interfaces. We can see this in practice with the Polyline component object we've used in earlier chapters. In Chapter 8, we eliminated the private members of the IPolyline5 interface that had to do with file input and output and replaced those members with the IPersistStorage and IPersistStreamInit interfaces. Now we can do the same thing in CHAP10\POLYLINE, replacing the data exchange members of IPolyline8, shown in the following, with IDataObject:


//From Chapter 8's Polyline
interface IPolyline8 : public IUnknown
{
[Other members]

STDMETHOD(DataSet) (THIS_ LPPOLYLINEDATA, BOOL, BOOL) PURE;
STDMETHOD(DataGet) (THIS_ LPPOLYLINEDATA) PURE;
STDMETHOD(DataSetMem) (THIS_ HGLOBAL, BOOL, BOOL, BOOL) PURE;
STDMETHOD(DataGetMem) (THIS_ HGLOBAL FAR *) PURE;
STDMETHOD(RenderBitmap) (THIS_ HBITMAP FAR *) PURE;
STDMETHOD(RenderMetafile) (THIS_ HMETAFILE FAR *) PURE;
STDMETHOD(RenderMetafilePict) (THIS_ HGLOBAL FAR *) PURE;

[Other members]
}

In other words, we can eliminate from IPolyline8 all the separate functions for exchange of its native data in both get and set directions because FORMATETC allows us to specify different formats and different mediums through IDataObject calls directly. The new interface, IPolyline10, for this chapter's version of Polyline no longer has these specific member functions.

In addition, Polyline has been working with its own private notification interface, IPolylineAdviseSink8, with members such as OnDataChange, OnPointChange, and so on. With the addition of IDataObject to the Polyline object, we can remove the OnDataChange member from the updated IPolylineAdviseSink10 interface and instead use IAdviseSink for this notification. Any client can now use Polyline for data exchange and notification without having to be aware of the custom IPolyline10 and IPolylineAdviseSink10 interfaces.

Along with these changes to Polyline are the necessary changes to Component Cosmo (CHAP10\COCOSMO), as follows:

None of the code to implement these features is much different from the code we've seen so far, so there's no need to show any of it here. However, with the addition of IDataObject along with IPersistStorage, the Polyline object is now very close to an embedded content object. What it lacks are the interfaces IViewObject2, which we'll see in the next chapter, and IOleObject, which we'll see in Chapter 19. Even when we make those changes, Component Cosmo can still use Polyline as before, totally ignoring any additional interfaces. This shows the flexibility of the multiple interface paradigm made possible by QueryInterface. In later chapters, we'll see how Polyline can support two different types of client (CoCosmo with inside knowledge and a container with no knowledge outside OLE Documents) merely by implementing a number of interfaces for both.