The best ideas are common property.
—Lucius Annaeus Seneca, c. 4 B.C.–A.D. 65
My guiding star always is, Get hold of portable property.
—John Huffam in Great Expectations, by Charles Dickens
Throughout many of the preceding chapters, we've explored ways through which a client and an object share their functionality and their information. In Chapters 2, 4, 5, and 6, we saw how clients and objects communicate. In Chapter 3, we saw how an object describes itself. In Chapters 7 and 8, we explored information storage, and in Chapter 9, we dealt with the naming of such information as well as the process of binding back to it again. In Chapters 10 through 13, we examined the means of exchanging structured data formats as well as the rendering and caching of graphic views of data. And in Chapters 14 and 15, we saw how an object can expose its functionality through late-bound methods and its information through individual properties using a dispID to identify a property in the context of an object.
Again, the common theme is that objects have functionality and content to share—objects share them in many ways. This chapter, the last before we explore the larger and more complex protocols of OLE Documents and OLE Controls, examines a number of additional considerations for an object's properties.
First we'll examine the user interface called property sheets, used for manipulating properties directly. Although property sheets have been seen in a number of applications for some time, no general mechanisms for creating them had been developed until recently. Windows 95 introduces this user interface on a system level, and OLE has its own set of interfaces and standards—namely property page components—that let you create property sheets in a more self-contained way. OLE-based property pages were introduced with OLE Controls as a standard means of manipulating a control's properties. The user interface, however, extends down to any object with properties, no matter how mundane that object. The key is that OLE's mechanism lets the object specify exactly which property pages to display, and those property pages can then communicate with the object in whatever way they want.
Next we'll discuss the use of an outgoing interface named IPropertyNotifySink through which a client can receive property change requests and property change notifications. This interface is especially useful when a mechanism such as property pages or an object's own user interface (such as for an OLE control) can change properties without the client itself having initiated the change. Because IPropertyNotifySink was designed at the same time as connection points (Chapter 4), a client uses that generic mechanism to connect its sink to the object and can then check for specific attributes in an object's type information in order to know which properties support the notifications in this interface.
Finally we'll look at a standard for the persistent storage of properties in what are called property sets. These are basically a sparse, flexible, and extensible stream format in which you can serialize almost any information you want. We will also see the specific property set named Summary Information, which, when attached to a compound file's root storage object, allows system shells such as that in Windows 95 to display such properties without otherwise opening the file or running the application that created it.
So as in earlier chapters we've seen how to exchange formatted data structures, how to notify a client of changes in such data, and how to access properties programmatically, here we'll see the standards for notifying a client of changes in individual properties, the standards for showing and accessing properties through a user interface, and the standards for accessing properties that exist in persistent storage.1 Thus we complete the picture, sharing an object's properties through code, user interface, and storage, and essentially making properties not only common but also portable.
1 At the time of writing, marshaling support does not exist for any of the interfaces introduced in this chapter. |