优化持久性和初始化

默认情况下,控件中的持久性和初始化由 DoPropExchange 成员函数处理。 在典型的控件中,此函数包含对多个PX_函数(PX_ColorPX_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();
}

尽管 SerializeOnResetState 重写,但函数应保持不变, DoPropExchange 因为它仍用于属性包格式的持久性。 请务必维护这三个函数,以确保控件一致地管理其属性,而不管容器使用哪种持久性机制。

另请参阅

MFC ActiveX 控件:优化