Udostępnij za pośrednictwem


Optymalizacja rysowania formantów

Gdy kontrolka zostanie poinstruowana, aby narysować się do kontekstu urządzenia dostarczonego przez kontener, zazwyczaj wybiera obiekty GDI (takie jak długopisy, pędzle i czcionki) w kontekście urządzenia, wykonuje operacje rysowania i przywraca poprzednie obiekty GDI. Jeśli kontener ma wiele kontrolek, które mają być rysowane w tym samym kontekście urządzenia, a każda kontrolka wybiera wymagane obiekty GDI, można zapisać czas, jeśli kontrolki nie przywracają wcześniej zaznaczonych obiektów indywidualnie. Po pobraniu wszystkich kontrolek kontener może automatycznie przywrócić oryginalne obiekty.

Aby wykryć, czy kontener obsługuje tę technikę, kontrolka może wywołać funkcję składową COleControl::IsOptimizedDraw . Jeśli ta funkcja zwróci wartość TRUE, kontrolka może pominąć normalny krok przywracania poprzednio zaznaczonych obiektów.

Rozważ kontrolkę, która ma następującą (niezoptymalizowaną) OnDraw funkcję:

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

Pióro i szczotka w tym przykładzie są zmiennymi lokalnymi, co oznacza, że ich destruktory będą wywoływane, gdy wyjdą poza zakres (po zakończeniu OnDraw funkcji). Destruktory podejmą próbę usunięcia odpowiednich obiektów GDI. Nie należy ich jednak usuwać, jeśli planujesz pozostawić je wybrane w kontekście urządzenia po powrocie z OnDraw.

Aby zapobiec niszczeniu obiektów CPen i CBrush po OnDraw zakończeniu, zapisz je w zmiennych członkowskich zamiast zmiennych lokalnych. W deklaracji klasy kontrolki dodaj deklaracje dla dwóch nowych zmiennych składowych:

class CMyAxOptCtrl : public COleControl
{
CPen m_pen;
CBrush m_brush;
};

OnDraw Następnie funkcję można przepisać w następujący sposób:

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

Takie podejście pozwala uniknąć tworzenia pióra i pędzla za każdym razem OnDraw . Zwiększenie szybkości wiąże się z kosztem utrzymania dodatkowych danych wystąpienia.

Jeśli właściwość ForeColor lub BackColor zmieni się, pióro lub pędzle należy utworzyć ponownie. W tym celu zastąpij funkcje składowe OnForeColorChanged i OnBackColorChanged :

void CMyAxOptCtrl::OnForeColorChanged()
{
   m_pen.DeleteObject();
}

void CMyAxOptCtrl::OnBackColorChanged()
{
   m_brush.DeleteObject();
}

Na koniec, aby wyeliminować niepotrzebne wywołania, zmodyfikuj SelectObject OnDraw w następujący sposób:

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

Zobacz też

Kontrolki ActiveX MFC: optymalizacja
Klasa COleControl
Kontrolki ActiveX MFC
Kreator kontrolek ActiveX MFC
Kontrolki ActiveX MFC: malowanie kontrolki ActiveX