Optimisation du contrôle de dessin

Lorsqu’un contrôle est invité à se dessiner dans un contexte d’appareil fourni par un conteneur, il sélectionne généralement des objets GDI (tels que des stylos, des pinceaux et des polices) dans le contexte de l’appareil, effectue ses opérations de dessin et restaure les objets GDI précédents. Si le conteneur a plusieurs contrôles à dessiner dans le même contexte d’appareil et que chaque contrôle sélectionne les objets GDI dont il a besoin, le temps peut être enregistré si les contrôles ne restaurent pas individuellement les objets précédemment sélectionnés. Une fois tous les contrôles dessinés, le conteneur peut restaurer automatiquement les objets d’origine.

Pour détecter si un conteneur prend en charge cette technique, un contrôle peut appeler la fonction membre COleControl ::IsOptimizedDraw . Si cette fonction retourne TRUE, le contrôle peut ignorer l’étape normale de restauration des objets précédemment sélectionnés.

Considérez un contrôle qui a la fonction suivante (non optimisée) OnDraw :

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

Le stylet et le pinceau de cet exemple sont des variables locales, ce qui signifie que leurs destructeurs sont appelés lorsqu’ils sortent de l’étendue (lorsque la OnDraw fonction se termine). Les destructeurs tenteront de supprimer les objets GDI correspondants. Mais ils ne doivent pas être supprimés si vous envisagez de les laisser sélectionnés dans le contexte de l’appareil lors du retour à partir de OnDraw.

Pour empêcher les objets CPen et CBrush d’être détruits une fois OnDraw terminés, stockez-les dans des variables membres au lieu de variables locales. Dans la déclaration de classe du contrôle, ajoutez des déclarations pour deux nouvelles variables membres :

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

Ensuite, la OnDraw fonction peut être réécrite comme suit :

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

Cette approche évite la création du stylet et du pinceau chaque fois OnDraw qu’elle est appelée. L’amélioration de la vitesse est le coût de la maintenance des données d’instance supplémentaires.

Si la propriété ForeColor ou BackColor change, le stylet ou le pinceau doit être recréé. Pour ce faire, remplacez les fonctions membres OnForeColorChanged et OnBackColorChanged :

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

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

Enfin, pour éliminer les appels inutiles SelectObject , modifiez OnDraw comme suit :

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

Voir aussi

Contrôles ActiveX MFC : optimisation
COleControl, classe
Contrôles ActiveX MFC
Contrôle ActiveX MFC, Assistant
Contrôles ActiveX MFC : peinture d’un contrôle ActiveX