optimiser le dessin de contrôle
Lorsqu'un contrôle est chargé de se dessiner dans un contexte de périphérique fourni par un conteneur, il sélectionne généralement des objets de GDI (tels que les stylets, les pinceaux, et les polices) dans le contexte de périphérique, exécute ses opérations de dessin, puis restaure les objets précédents de GDI. Si le conteneur comporte plusieurs commandes qui doivent être dessinées dans le même contexte de périphérique, et si chaque contrôle sélectionne les objets de GDI qu'il requiert, du temps peut être gagné si les contrôles ne restaurent pas individuellement les objets précédemment sélectionnés. Une fois que tous les contrôles ont été faits, le conteneur peut automatiquement restaurer des objets d'origine.
Pour détecter si un conteneur prend en charge cette technique, un contrôle peut appeler la fonction membre d' COleControl::IsOptimizedDraw. Si cette fonction retourne TRUE, le contrôle peut ignorer la phase de restauration normale des objets précédemment sélectionnés.
Considérez un contrôle qui a la fonction (non) optimisée d' OnDraw suivante :
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 stylo et le pinceau dans cet exemple sont des variables locales, ce qui signifie que leurs destructeurs sont appelés lorsqu'ils deviennent hors de portée (lorsque la fonction d' OnDraw finit). Les destructeurs tentent de supprimer les objets correspondants de GDI. Ils ne doivent pas être supprimés si vous envisagez de les laisser sélectionnés dans le contexte de périphérique lors de le retour d' OnDraw.
Pour empêcher les objets d' CPen et d' CBrush d'être détruits lorsque OnDraw se termine, enregistrez-les dans des variables membre au lieu des variables locales. Dans la déclaration de la classe de contrôle, ajoutez les déclarations de deux nouvelles variables membres :
class CMyAxOptCtrl : public COleControl
{
...
CPen m_pen;
CBrush m_brush;
};
Puis, la fonction de OnDraw peut alors ê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 qu' OnDraw est appelé. L'amélioration de la vitesse provient au détriment de la conservation des données d'instance supplémentaires.
Si la propriété ForeColor ou BackColor change, le stylet ou le pinceau doit être créé à nouveau. Pour faire ceci, substituez les fonctions membres d' OnForeColorChanged et d' OnBackColorChanged:
void CMyAxOptCtrl::OnForeColorChanged()
{
m_pen.DeleteObject();
}
void CMyAxOptCtrl::OnBackColorChanged()
{
m_brush.DeleteObject();
}
Enfin, pour éliminer les appels inutiles d' 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
Référence
Contrôle ActiveX MFC (Assistant)