The Property
Map
The ATL implementation of these three
persistence interfaces requires that your object provide a table
that describes all the properties that should be saved and loaded
during a persistence operation. This table is called the
property map. ATL uses the
property map of a class for two independent purposes: persistence
support and control property page support (discussed in Chapter 11, "ActiveX
Controls").
The various property map entries enable you to
do the following:
-
Define the properties of the COM object that the
ATL persistence-implementation classes save and restore during a
persistence request
-
Define the member variables of the C++ class
that the ATL persistence-implementation classes save and restore
during a persistence request
-
Define the property pages that a class uses
-
Associate a property with its property page
The CDemagogue class's property map
looks like this:
BEGIN_PROP_MAP(CDemagogue)
PROP_ENTRY_EX("Speech", DISPID_SPEECH,
CLSID_NULL, IID_ISpeaker)
PROP_ENTRY_EX("Volume", DISPID_VOLUME,
CLSID_NULL, IID_ISpeaker)
PROP_ENTRY_EX("Name", DISPID_NAME,
CLSID_NULL, IID_INamedObject)
END_PROP_MAP()
The BEGIN_PROP_MAP and
END_PROP_MAP macros define a class's property map. You
list the persistent properties of an object in the property map
using the PROP_ENTRY and PROP_ENTRY_EX macros.
The PROP_ENTRY macro describes a property that the
persistence implementation can access via the default dispatch
interfacein other words, the interface retrieved when you query for
IID_IDispatch. You use the PROP_ENTRY_EX macro to
describe a property that the persistence implementation must access
using some other specified dispatch interface. Both macros require
the name of the property, the property's DISPID, and the CLSID of
the property's associated property page (discussed in Chapter 11). The
PROP_ENTRY_EX macro also requires the IID of the dispatch
interface that supports the specified property; the
PROP_ENTRY macro uses IID_IDispatch.
PROP_ENTRY (szDesc, dispid, clsid)
PROP_ENTRY_EX (szDesc, dispid, clsid, iidDispatch)
PROP_DATA_ENTRY (szDesc, member, vt)
You might also want to load and save member
variables of your object that are not accessible via a dispatch
interface. The PROP_DATA_ENTRY macro enables you to
specify the name of a property, the member variable containing the
value, and the VARIANT type of the variable, like so:
BEGIN_PROP_MAP(CBullsEye)
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
...
END_PROP_MAP()
Effectively, the PROP_DATA_ENTRY macro
causes the persistence implementation to reach into your object,
access the specified member variable for the length implied by the
VARIANT type, place the data into a VARIANT, and
write the VARIANT to the persistent medium. This is quite
handy when you have a member variable that is a
VARIANT-compatible type. However, it doesn't work for
noncompatible types such as indexed properties. Note that a
PROP_PAGE macro also is used to associate a property to a property page; I discuss its use in
Chapter 11, "ActiveX
Controls." The persistence implementations skip entries in the
property map made with the PROP_PAGE macro.
One caution: Don't add a PROP_ENTRY,
PROP_ENTRY_EX, or PROP_DATA_ENTRY macro that has
a property name with an embedded space character. Some relatively
popular containers, such as Visual Basic 6, provide an
implementation of IPropertyBag that cannot handle names
with embedded spaces.
When you have a member variable that you want to
load and save during a persistence operation, and that variable is
not a VARIANT-compatible type (for example, an indexed or
array variable), the property map mechanism doesn't help. You have
to override the appropriate member functions of the persistence
implementation classes, and read and write the variable explicitly.
To do this, you need to know the basic structure of the ATL
persistence implementation.
|