根據預設,控件中的持續性和初始化是由成員函式處理 DoPropExchange 。 在一般控制元件中,此函式包含對數個PX_函式的呼叫,每個屬性都有一個呼叫,例如PX_Color、PX_Font等。
這種方法的優點是,單 DoPropExchange 一實作可用於初始化、二進位格式的持續性,以及某些容器所使用的所謂「屬性包」格式的持續性。 此一個函式會在一個方便的地方提供屬性及其預設值的所有資訊。
然而,這種普遍性是以效率為代價。 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...
}
請注意,在載入案例中,會使用暫存變數,然後指派其值,而不是將 m_boolProp 轉換成 BYTE 參考。 轉換技術將只修改 m_boolProp 的一個位元組,其餘的位元組將保持未初始化狀態。
針對相同的控件,您可以覆寫 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 函數應保持完整,因為它仍然用於屬性包格式的持續性。 請務必維護這三個函式,以確保控件會一致地管理其屬性,而不論容器所使用的持續性機制為何。