Optimalizace vykreslování ovládacích prvků
Když je ovládací prvek instruován, aby se nakreslil do kontextu zařízení dodaného kontejnerem, obvykle vybere objekty GDI (například pera, štětce a písma) do kontextu zařízení, provede své operace kreslení a obnoví předchozí objekty GDI. Pokud má kontejner více ovládacích prvků, které se mají nakreslit do stejného kontextu zařízení, a každý ovládací prvek vybere objekty GDI, které vyžaduje, může být čas uložen, pokud ovládací prvky jednotlivě neobnoví dříve vybrané objekty. Po nakreslení všech ovládacích prvků může kontejner automaticky obnovit původní objekty.
Chcete-li zjistit, zda kontejner podporuje tuto techniku, může ovládací prvek volat COleControl::IsOptimizedDraw členské funkce. Pokud tato funkce vrátí hodnotu PRAVDA, může ovládací prvek přeskočit normální krok obnovení dříve vybraných objektů.
Zvažte ovládací prvek, který má následující (neoptimalizovanou) OnDraw
funkci:
void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
CPen pen(PS_SOLID, 0, TranslateColor(GetForeColor()));
CBrush brush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&pen);
CBrush* pBrushSave = pdc->SelectObject(&brush);
pdc->Rectangle(rcBounds);
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
Pero a štětec v tomto příkladu jsou místní proměnné, což znamená, že jejich destruktory budou volány, když přejdou mimo rozsah (když OnDraw
funkce skončí). Destruktory se pokusí odstranit odpovídající objekty GDI. Ale neměly by být odstraněny, pokud máte v úmyslu nechat je vybrané v kontextu zařízení po návratu z OnDraw
.
Chcete-li zabránit zničení objektů CPen a CBrush po OnDraw
dokončení, uložte je do členských proměnných místo místních proměnných. V deklaraci třídy ovládacího prvku přidejte deklarace pro dvě nové členské proměnné:
class CMyAxOptCtrl : public COleControl
{
CPen m_pen;
CBrush m_brush;
};
OnDraw
Pak můžete funkci přepsat následujícím způsobem:
void OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
CPen pen(PS_SOLID, 0, TranslateColor(GetForeColor()));
CBrush brush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&pen);
CBrush* pBrushSave = pdc->SelectObject(&brush);
pdc->Rectangle(rcBounds);
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
Tento přístup zabraňuje vytvoření pera a kartáče při každém OnDraw
zavolání. Vylepšení rychlosti je nákladné udržovat další data instance.
Pokud foreColor nebo BackColor vlastnost změní, pero nebo štětec musí být znovu vytvořen. Uděláte to tak, že přepíšete členské funkce OnForeColorChanged a OnBackColorChanged :
void CMyAxOptCtrl::OnForeColorChanged()
{
m_pen.DeleteObject();
}
void CMyAxOptCtrl::OnBackColorChanged()
{
m_brush.DeleteObject();
}
Nakonec, abyste eliminovali nepotřebná SelectObject
volání, upravte OnDraw
je takto:
void CMyAxOptCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
if (m_pen.m_hObject == NULL)
m_pen.CreatePen(PS_SOLID, 0, TranslateColor(GetForeColor()));
if (m_brush.m_hObject == NULL)
m_brush.CreateSolidBrush(TranslateColor(GetBackColor()));
CPen* pPenSave = pdc->SelectObject(&m_pen);
CBrush* pBrushSave = pdc->SelectObject(&m_brush);
pdc->Rectangle(rcBounds);
if (!IsOptimizedDraw())
{
pdc->SelectObject(pPenSave);
pdc->SelectObject(pBrushSave);
}
}
Viz také
MFC – ovládací prvky ActiveX: Optimalizace
COleControl – třída
MFC – ovládací prvky ActiveX
Průvodce ovládacím prvkem ActiveX v prostředí MFC
MFC – ovládací prvky ActiveX: Vykreslování ovládacího prvku ActiveX