既定では、コントロールの永続化と初期化は、 DoPropExchange
メンバー関数によって処理されます。 一般的なコントロールでは、この関数には、プロパティごとに 1 つずつ、複数の PX_ 関数 (PX_Color
、 PX_Font
など) の呼び出しが含まれています。
この方法には、初期化、バイナリ形式での永続化、一部のコンテナーで使用されるいわゆる "プロパティ バッグ" 形式での永続化に、1 つの DoPropExchange
実装を使用できるという利点があります。 この 1 つの関数は、プロパティとその既定値に関するすべての情報を 1 か所で提供します。
ただし、この一般化は効率を犠牲にしています。 PX_関数は、より直接的で柔軟性の低いアプローチよりも本質的に効率の低い多層実装を通じて柔軟性を得ます。 さらに、コントロールが 既定値をPX_ 関数に渡す場合は、既定値が必ずしも使用されない場合でも、その既定値を毎回指定する必要があります。 既定値の生成が一般タスクである場合 (たとえば、アンビエント プロパティから値が取得された場合)、既定値が使用されていない場合は不要な作業が余分に行われます。
コントロールの Serialize
関数をオーバーライドすることで、コントロールのバイナリ永続化のパフォーマンスを向上させることができます。 このメンバー関数の既定の実装では、DoPropExchange
関数の呼び出しが行われます。 これをオーバーライドすることで、バイナリ永続化のためのより直接的な実装を提供できます。 たとえば、次の DoPropExchange
関数について考えてみましょう。
void CMyAxOptCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
PX_Bool(pPX, _T("BoolProp"), m_BoolProp, TRUE);
PX_Short(pPX, _T("ShortProp"), m_ShortProp, 0);
PX_Color(pPX, _T("ColorProp"), m_ColorProp, RGB(0xFF, 0x00, 0x00));
PX_String(pPX, _T("StringProp"), m_StringProp, _T(""));
}
このコントロールのバイナリ永続化のパフォーマンスを向上させるには、次のように Serialize
関数をオーバーライドします。
void CMyAxOptCtrl::Serialize(CArchive& ar)
{
SerializeVersion(ar, MAKELONG(_wVerMinor, _wVerMajor));
SerializeExtent(ar);
SerializeStockProps(ar);
if (ar.IsLoading())
{
ar >> m_BoolProp;
ar >> m_ShortProp;
ar >> m_ColorProp;
ar >> m_StringProp;
}
else
{
ar << m_BoolProp;
ar << m_ShortProp;
ar << m_ColorProp;
ar << m_StringProp;
}
}
dwVersion
ローカル変数を使用して、読み込みまたは保存されているコントロールの永続的な状態のバージョンを検出できます。 CPropExchange::GetVersion を呼び出す代わりに、この変数を使用できます。
BOOL プロパティの永続的な形式で少し領域を節約するには (また、PX_Bool
によって生成された形式と互換性を保つために)、次のように、プロパティを BYTE として格納できます。
if (ar.IsLoading())
{
BYTE bTmp;
ar >> bTmp;
m_BoolProp = (BOOL)bTmp;
// other properties...
}
else
{
ar << (BYTE)m_BoolProp;
// other properties...
}
読み込み時には、BYTE 参照にm_boolPropをキャストするのではなく、一時変数が使用され、その値が割り当てられることに注意してください。 キャスト手法では、 m_boolPropの 1 バイトのみが変更され、残りのバイトは初期化されません。
同じコントロールの場合、 次のように COleControl::OnResetState をオーバーライドすることで、コントロールの初期化を最適化できます。
void CMyAxOptCtrl::OnResetState()
{
ResetVersion(MAKELONG(_wVerMinor, _wVerMajor));
ResetStockProps();
m_BoolProp = TRUE;
m_ShortProp = 0;
m_ColorProp = RGB(0xFF, 0x00, 0x00);
m_StringProp.Empty();
}
Serialize
とOnResetState
はオーバーライドされていますが、DoPropExchange
関数はプロパティ バッグ形式での永続化に引き続き使用されるため、そのまま保持する必要があります。 コンテナーが使用する永続化メカニズムに関係なく、コントロールがそのプロパティを一貫して管理できるように、これらの 3 つの関数すべてを維持することが重要です。