Optymalizacja rysowania formantów
Kiedy formant został zobowiązany zwrócić się do kontekstu urządzenia dostarczony kontenera, to zazwyczaj wybiera obiekty GDI (takich jak pióra, pędzle i czcionki) do kontekstu urządzenia, wykonuje swoją działalność rysunku oraz przywraca poprzednie obiekty interfejsu GDI.Jeśli kontener posiada wiele formantów, które mają być tworzone w tym samym kontekście urządzenia, a każdy formant wybiera obiekty interfejsu GDI, które wymaga, czas może być zapisany, jeśli formanty indywidualnie nie przywrócić poprzednio zaznaczonych obiektów.Po wszystkie formanty zostały wystawione, pojemnika można automatycznie przywrócić oryginalne obiekty.
W celu wykrycia, czy kontener obsługuje tę technikę, formant można wywołać COleControl::IsOptimizedDraw funkcji składowej.Jeśli funkcja ta zwróci TRUE, formant można pominąć krok normalnego przywracania poprzednio zaznaczonych obiektów.
Należy wziąć pod uwagę formantu, który ma następujące (unoptimized) OnDraw funkcji:
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 Ołówek w tym przykładzie są zmienne lokalne, co oznacza ich destruktorów będzie wywoływany, gdy przejdą poza zakresem (po OnDraw funkcja kończy się).Destruktory spróbuje usunąć odpowiednie obiekty interfejsu GDI.Ale one nie powinny być usuwane Jeśli planuje się pozostawienie ich wybranych do kontekstu urządzenia po powrocie z OnDraw.
Aby zapobiec CPen i CBrush obiektów przed zniszczeniem podczas OnDraw wykończenie, przechowywać je w zmienne składowe zamiast zmiennych lokalnych.W deklaracji klasy formantu Dodaj zgłoszeń o dwie nowe zmienne składowe:
class CMyAxOptCtrl : public COleControl
{
...
CPen m_pen;
CBrush m_brush;
};
Następnie, OnDraw funkcji można zapisać 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);
}
Podejście to pozwala uniknąć tworzenia Pióro i Pędzel zawsze OnDraw nazywa się.Poprawę szybkości wiążą się z obsługi danych dodatkowe wystąpienie.
Jeśli właściwość BackColor lub ForeColor zmiany, Pióro lub pędzla musi zostać utworzony ponownie.Aby to zrobić, należy zastąpić OnForeColorChanged i OnBackColorChanged funkcji elementów członkowskich:
void CMyAxOptCtrl::OnForeColorChanged()
{
m_pen.DeleteObject();
}
void CMyAxOptCtrl::OnBackColorChanged()
{
m_brush.DeleteObject();
}
Wreszcie aby wyeliminować zbędne SelectObject modyfikowanie połączeń, 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);
}
}