Optimieren der Steuerelementdarstellung

Wenn ein Steuerelement angewiesen wird, sich in einen containerbezogenen Gerätekontext zu zeichnen, wählt es in der Regel GDI-Objekte (z. B. Stifte, Pinsel und Schriftarten) in den Gerätekontext aus, führt seine Zeichnungsvorgänge aus und stellt die vorherigen GDI-Objekte wieder her. Wenn der Container über mehrere Steuerelemente verfügt, die in denselben Gerätekontext gezeichnet werden sollen, und jedes Steuerelement wählt die benötigten GDI-Objekte aus, kann Zeit gespeichert werden, wenn die Steuerelemente zuvor ausgewählte Objekte nicht einzeln wiederherstellen. Nachdem alle Steuerelemente gezeichnet wurden, kann der Container die ursprünglichen Objekte automatisch wiederherstellen.

Um zu ermitteln, ob ein Container diese Technik unterstützt, kann ein Steuerelement die Memberfunktion "COleControl::IsOptimizedDraw " aufrufen. Wenn diese Funktion WAHR zurückgibt, kann das Steuerelement den normalen Schritt der Wiederherstellung der zuvor ausgewählten Objekte überspringen.

Betrachten Sie ein Steuerelement mit der folgenden (nicht optimierten) OnDraw Funktion:

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

Der Stift und der Pinsel in diesem Beispiel sind lokale Variablen, was bedeutet, dass ihre Destruktoren aufgerufen werden, wenn sie außerhalb des Gültigkeitsbereichs (wenn die OnDraw Funktion endet). Die Destruktoren versuchen, die entsprechenden GDI-Objekte zu löschen. Sie sollten jedoch nicht gelöscht werden, wenn Sie beabsichtigen, sie beim Zurückkehren in OnDrawden Gerätekontext zu übernehmen.

Um zu verhindern, dass die CPen - und CBrush-Objekte nach OnDraw Abschluss zerstört werden, speichern Sie sie in Membervariablen anstelle lokaler Variablen. Fügen Sie in der Klassendeklaration des Steuerelements Deklarationen für zwei neue Membervariablen hinzu:

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

Anschließend kann die OnDraw Funktion wie folgt umgeschrieben werden:

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

Bei diesem Ansatz wird die Erstellung des Stifts und des Pinsels bei jedem OnDraw Aufruf vermieden. Die Geschwindigkeitsverbesserung entsteht durch die Standard Nachhaltigen zusätzlicher Instanzdaten.

Wenn sich die ForeColor- oder BackColor-Eigenschaft ändert, muss der Stift oder Pinsel erneut erstellt werden. Setzen Sie dazu die Memberfunktionen "OnForeColorChanged " und "OnBackColorChanged " außer Kraft:

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

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

Um unnötige Aufrufe SelectObject zu beseitigen, ändern Sie OnDraw folgendes:

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

Siehe auch

MFC-ActiveX-Steuerelemente: Optimierung
COleControl-Klasse
MFC ActiveX Controls (MFC-ActiveX-Steuerelemente)
MFC-ActiveX-Steuerelement-Assistent
MFC-ActiveX-Steuerelemente: Darstellen eines ActiveX-Steuerelements