Compartir a través de


Optimización del dibujo de controles

Cuando se indica a un control que se dibuje en un contexto de dispositivo proporcionado por el contenedor, normalmente selecciona objetos GDI (como lápices, pinceles y fuentes) en el contexto del dispositivo, realiza sus operaciones de dibujo y restaura los objetos GDI anteriores. Si el contenedor tiene varios controles que se van a dibujar en el mismo contexto de dispositivo y cada control selecciona los objetos GDI que requiere, se puede guardar el tiempo si los controles no restauran individualmente los objetos seleccionados anteriormente. Una vez dibujados todos los controles, el contenedor puede restaurar automáticamente los objetos originales.

Para detectar si un contenedor admite esta técnica, un control puede llamar a la función miembro COleControl::IsOptimizedDraw . Si esta función devuelve TRUE, el control puede omitir el paso normal de restaurar los objetos seleccionados anteriormente.

Considere un control que tenga la siguiente función (nooptimizada): 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);
}

El lápiz y el pincel de este ejemplo son variables locales, lo que significa que se llamará a sus destructores cuando salgan del ámbito (cuando finalice la función OnDraw). Los destructores intentarán eliminar los objetos GDI correspondientes. Pero no deben eliminarse si planea dejarlas seleccionadas en el contexto del dispositivo al volver de OnDraw.

Para evitar que los objetos CPen y CBrush se destruyan cuando OnDraw terminen, almacénelos en variables miembro en lugar de variables locales. En la declaración de clase del control, agregue declaraciones para dos nuevas variables miembro:

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

A continuación, la función se puede volver a escribir de la OnDraw siguiente manera:

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

Este enfoque evita la creación del lápiz y el pincel cada vez que se llama a OnDraw. La mejora de la velocidad conlleva el costo de mantener datos de instancia adicionales.

Si cambia la propiedad ForeColor o BackColor, es necesario volver a crear el lápiz o el pincel. Para ello, invalide las funciones miembro OnForeColorChanged y OnBackColorChanged :

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

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

Por último, para eliminar las llamadas innecesarias SelectObject , modifique OnDraw de la siguiente manera:

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

Consulte también

Controles ActiveX de MFC: Optimización
Clase COleControl
Controles ActiveX de MFC
Asistente para controles ActiveX de MFC
Controles ActiveX de MFC: Pintar un control ActiveX