需要保存自身状态的object应该提供IPersistMedium,这里Medium=Stream,Storage,PropertyBag等
client决定何时在何种媒体上要保存object的状态,调用IPersistMedium的Load(),Save(),并且为这两个函数提供相应的IMedium接口
所有的IPersistMedium都派生自IPersist接口:
interface IPersist : IUnknown { HRESULT GetClassID([out] CLSID* pclsid); }
object可以提供2种数据:
self-describing set,用户可读数据:例如txt,html,xml形式
opaque binary stream of bytes,流媒体数据:只有机器才能明白
IPropertyBag and IPersistPropertyBag
interface IPropertyBag : public IUnknown { HRESULT Read([in] LPCOLESTR pszPropName, [in, out] VARIANT* pVar, [in] IErrorLog* pErrorLog); HRESULT Write([in] LPCOLESTR pszPropName, [in] VARIANT* pVar); }; interface IPersistPropertyBag : public IPersist { HRESULT InitNew (); HRESULT Load([in] IPropertyBag* pPropBag, [in] IErrorLog* pErrorLog); HRESULT Save([in] IPropertyBag* pPropBag, [in] BOOL fClearDirty, [in] BOOL fSaveAllProperties); };
IPropertyBag2 and IPersistPropertyBag2
interface IPropertyBag2 : public IUnknown { HRESULT Read([in] ULONG cProperties, [in] PROPBAG2* pPropBag, [in] IErrorLog* pErrLog, [out] VARIANT* pvarValue, [out] HRESULT* phrError); HRESULT Write([in] ULONG cProperties, [in] PROPBAG2* pPropBag, [in] VARIANT* pvarValue); HRESULT CountProperties ([out] ULONG* pcProperties); HRESULT GetPropertyInfo([in] ULONG iProperty, [in] ULONG cProperties, [out] PROPBAG2* pPropBag, [out] ULONG* pcProperties); HRESULT LoadObject([in] LPCOLESTR pstrName, [in] DWORD dwHint, [in] IUnknown* pUnkObject, [in] IErrorLog* pErrLog); }; interface IPersistPropertyBag2 : public IPersist { HRESULT InitNew (); HRESULT Load ([in] IPropertyBag2* pPropBag, [in] IErrorLog* pErrLog); HRESULT Save ([in] IPropertyBag2* pPropBag, [in] BOOL fClearDirty, [in] BOOL fSaveAllProperties); HRESULT IsDirty(); };
IPropertyBag2可以通过CountProperties()和GetPropertyInfo()了解Property的数量和类型
IPropertyBag2应该支持IPropertyBag的功能
IPersistPropertyBag2应该支持IPersistPropertyBag
The IStream, IpersistStreamInit, and IPersistStream Interfaces
ActiveX需要实现IpersistStreamInit或者IPersistStream
interface ISequentialStream : IUnknown { HRESULT Read([out] void *pv, [in] ULONG cb, [out] ULONG *pcbRead); HRESULT Write( [in] void const *pv, [in] ULONG cb, [out] ULONG *pcbWritten); } interface IStream : ISequentialStream { HRESULT Seek([in] LARGE_INTEGER dlibMove, [in] DWORD dwOrigin, [out] ULARGE_INTEGER *plibNewPosition); //... } interface IPersistStreamInit : public IPersist { HRESULT IsDirty(); HRESULT Load([in] LPSTREAM pStm); HRESULT Save([in] LPSTREAM pStm, [in] BOOL fClearDirty); HRESULT GetSizeMax([out] ULARGE_INTEGER*pCbSize); HRESULT InitNew(); }; interface IPersistStream : public IPersist { HRESULT IsDirty(); HRESULT Load([in] LPSTREAM pStm); HRESULT Save([in] LPSTREAM pStm, [in] BOOL fClearDirty); HRESULT GetSizeMax([out] ULARGE_INTEGER*pCbSize); };
IPersistStreamInit和IPersistStream如果全部实现,例子:
class ATL_NO_VTABLE CDemagogue : public IPersistStreamInit, ... {
...
BEGIN_COM_MAP(CDemagogue)
...
COM_INTERFACE_ENTRY(IPersistStreamInit)
COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStreamInit)
COM_INTERFACE_ENTRY2(IPersist, IPersistStreamInit)
END_COM_MAP()
...
};
IStorage and IPersistStorage
该接口用于OLE linking and embeding
interface IStorage : public IUnknown { HRESULT CreateStream([string,in] const OLECHAR* pwcsName, [in] DWORD grfMode, [in] DWORD reserved1, [in] DWORD reserved2, [out] IStream** ppstm); HRESULT OpenStream([string,in] const OLECHAR* pwcsName, [unique][in] void* reserved1, [in] DWORD grfMode, [in] DWORD reserved2, [out] IStream** ppstm); HRESULT CreateStorage([string,in] const OLECHAR* pwcsName, [in] DWORD grfMode, [in] DWORD reserved1, [in] DWORD reserved2, [out] IStorage** ppstg); HRESULT OpenStorage( [string,unique,in] const OLECHAR* pwcsName, [unique,in] IStorage* pstgPriority, [in] DWORD grfMode, [unique,in] SNB snbExclude, [in] DWORD reserved, [out] IStorage** ppstg); // Following methods abbreviated for clarity... HRESULT CopyTo( ... ); HRESULT MoveElementTo( ... ) HRESULT Commit( ... ) HRESULT Revert(void); HRESULT EnumElements( ... ); HRESULT DestroyElement( . ., ); HRESULT RenameElement( ... ); HRESULT SetElementTimes( ... ); HRESULT SetClass( ... ); HRESULT SetStateBits( ... ); HRESULT Stat( ... ); }; interface IPersistStorage : public IPersist { HRESULT IsDirty (); HRESULT InitNew ([unique,in] IStorage* pStg); HRESULT Load ([unique,in] IStorage* pStg); HRESULT Save ([unique,in] IStorage* pStgSave, [in] BOOL fSameAsLoad); HRESULT SaveCompleted ([unique,in] IStorage* pStgNew); HRESULT HandsOffStorage (); };
ATL实现的例子:
class ATL_NO_VTABLE CDemagogue : public IPersistPropertyBagImpl<CDemagogue>, public IPersistStreamInitImpl<CDemagogue>, public IPersistStorageImpl<CDemagogue> { ... BEGIN_COM_MAP(CDemagogue) ... COM_INTERFACE_ENTRY2(IPersist, IPersistPropertyBag) COM_INTERFACE_ENTRY(IPersistPropertyBag) COM_INTERFACE_ENTRY(IPersistStreamInit) COM_INTERFACE_ENTRY(IPersistStream) COM_INTERFACE_ENTRY(IPersistStorage) END_COM_MAP() ... };