Optymalizacja stanu trwałego i inicjalizacji

Domyślnie trwałość i inicjowanie w kontrolce są obsługiwane przez funkcję składową DoPropExchange . W typowej kontrolce ta funkcja zawiera wywołania kilku funkcji PX_ (PX_Color, PX_Fontitd.), po jednym dla każdej właściwości.

Takie podejście ma zaletę, że pojedyncza DoPropExchange implementacja może służyć do inicjowania, trwałości w formacie binarnym i trwałości w tak zwanym formacie "property-bag" używanym przez niektóre kontenery. Ta jedna funkcja udostępnia wszystkie informacje o właściwościach i ich wartościach domyślnych w jednym wygodnym miejscu.

Jednak ta ogólnalność wiąże się z kosztem wydajności. Funkcje PX_ zapewniają elastyczność dzięki wielowarstwowym implementacjom, które są z natury mniej wydajne niż bardziej bezpośrednie, ale mniej elastyczne. Ponadto jeśli kontrolka przekazuje wartość domyślną do funkcji PX_ , ta wartość domyślna musi być podana za każdym razem, nawet w sytuacjach, gdy wartość domyślna może nie być używana. Jeśli generowanie wartości domyślnej jest zadaniem nietrywialnym (na przykład gdy wartość jest uzyskiwana z właściwości otoczenia), dodatkowa niepotrzebna praca jest wykonywana w przypadkach, gdy wartość domyślna nie jest używana.

Wydajność trwałości binarnej kontrolki można poprawić, przesłaniając funkcję kontrolki Serialize . Domyślna implementacja tej funkcji składowej wykonuje wywołanie DoPropExchange funkcji. Przesłaniając ją, można zapewnić bardziej bezpośrednią implementację dla trwałości binarnej. Rozważmy na przykład tę DoPropExchange funkcję:

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(""));
}

Aby zwiększyć wydajność trwałości binarnej tej kontrolki, można zastąpić Serialize funkcję w następujący sposób:

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;
   }
}

Zmienna lokalna dwVersion może służyć do wykrywania wersji stanu trwałego, który jest ładowany lub zapisywany. Tej zmiennej można użyć zamiast wywoływać CPropExchange ::GetVersion.

Aby zaoszczędzić trochę miejsca w formacie trwałym dla właściwości BOOL (i zachować jej zgodność z formatem utworzonym przez PX_Boolprogram ), można przechowywać właściwość jako BYTE w następujący sposób:

if (ar.IsLoading())
{
   BYTE bTmp;
   ar >> bTmp;
   m_BoolProp = (BOOL)bTmp;
   // other properties...
}
else
{
   ar << (BYTE)m_BoolProp;
   // other properties...
}

Należy pamiętać, że w przypadku obciążenia jest używana zmienna tymczasowa, a następnie jej wartość jest przypisywana, a nie rzutowanie m_boolProp do odwołania BYTE . Technika rzutowania spowoduje zmodyfikowanie tylko jednego bajtu m_boolProp , pozostawiając pozostałe bajty niezainicjowane.

Dla tej samej kontrolki można zoptymalizować inicjowanie kontrolki przez zastąpienie COleControl::OnResetState w następujący sposób:

void CMyAxOptCtrl::OnResetState()
{
   ResetVersion(MAKELONG(_wVerMinor, _wVerMajor));
   ResetStockProps();

   m_BoolProp = TRUE;
   m_ShortProp = 0;
   m_ColorProp = RGB(0xFF, 0x00, 0x00);
   m_StringProp.Empty();
}

Mimo że Serialize i OnResetState zostały zastąpione, funkcja powinna być zachowana bez zmian, DoPropExchange ponieważ jest nadal używana do trwałości w formacie właściwości-bag. Ważne jest, aby zachować wszystkie trzy z tych funkcji, aby upewnić się, że kontrolka zarządza jej właściwościami spójnie, niezależnie od tego, który mechanizm trwałości używa kontenera.

Zobacz też

Kontrolki ActiveX MFC: optymalizacja