Introduction
I have had to make an ActiveX container with the possibility to contain several controls (~100,200,600...). Apart from drawing considerations and optimizations, saving and loading times of controls may be a drawback when the number of them increase. And why? If you see the ATL code for the serialization of control's properties, you find the BEGIN_PROP_MAP()
macro that defines, the properties of the controls that are serialized "one by one". At this point, is where resided my improvement.
Control properties serialization
See the following sample of ATL-Map with the properties of a control to serialize:
BEGIN_PROP_MAP(CMyControl
PROP_DATA_ENTRY("_cx", m_sizeExtent.cx, VT_UI4)
PROP_DATA_ENTRY("_cy", m_sizeExtent.cy, VT_UI4)
PROP_DATA_ENTRY("value", m_nValue, VT_I4)
PROP_DATA_ENTRY("mask", m_nMask, VT_I4)
PROP_ENTRY("SafFile", DISPID_CTCSafFile, CLSID_NULL)
... etc.
END_PROP_MAP()
As you can see, properties' serialization are defined one by one. When the control is saved, this is translated to internal calls to IPersistStreamInit::Save()
, and same when the control is loaded, with IPersistStreamInit::Load()
. The key here is that, every PROP_DATA_ENTRY
macro has an intrinsic call to IPersisteStreamInit::Load()
or Save()
(remember that an ATL-ActiveX control inherits and implements this interface by IPersistStreamInitImpl<>
template).
If you have hundred of controls to save at the same time, and they have several properties saving or loading by one call to IPersistStreamInit
interface per property, this may take several time. This can be improved by the following code:
BEGIN_PROP_MAP(CMyControl)
END_PROP_MAP()
typedef struct CONTROLPROPERTIES
{
} CONTROLPROPERTIES;
CONTROLPROPERTIES m_properties;
public:
STDMETHOD(Load)( LPSTREAM pStm )
{
if ( pStm == NULL ) return( E_POINTER );
pStm->Read( &m_properties, sizeof(m_properties), NULL );
return( S_OK );
}
STDMETHOD(Save)( LPSTREAM pStm, BOOL fClearDirty )
{
if ( pStm == NULL ) return( E_POINTER );
pStm->Write( &m_properties, sizeof(m_properties), NULL );
if ( fClearDirty ) SetDirty(FALSE);
return( S_OK );
}
With this way for saving and loading, every control is saved or loaded with an unique call to IPersistStreamInit::Save()
or Load()
, not one call per property, and so we can save time!!!