Compartilhar via


Otimizando o desenho de controle

Quando um controle for instruído a ser desenhado em um contexto fornecido do dispositivo, normalmente seleciona objetos de GDI (como penalidades, escovas, e fontes) no contexto do dispositivo, executa suas operações de desenho, e restaura os objetos anteriores de GDI. Se o contêiner tem vários controles que devem ser desenhados no mesmo contexto do dispositivo, e cada controle seleciona os objetos de GDI requer, o tempo podem ser salvos se os controles não restauração individualmente objetos selecionados anteriormente. Os controles foram extraídos depois, o contêiner automaticamente podem restaurar os objetos originais.

Para detectar se um contêiner da suporte a essa técnica, um controle pode chamar a função de membro de COleControl::IsOptimizedDraw . Se esta função retorna Verdadeiro, o controle pode passar à etapa normal de restaurar os objetos selecionados anteriormente.

Considere um controle que tem a seguinte função (unoptimized) de 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);
}

A caneta e a escova neste exemplo são variáveis locais, o que significa que seus destruidores serão chamados quando sair do escopo (quando a função de OnDraw termina). Os destruidores tentarão excluir os objetos correspondentes de GDI. Mas não devem ser excluídos se você planeja os deixar selecionados no contexto do dispositivo de retornar de OnDraw.

Para impedir que os objetos de CPen e de CBrush serem destruídos quando OnDraw é concluída, os armazena em variáveis de membro em vez de variáveis locais. Na declaração de classe de controle, adicione instruções para dois novos variáveis de membro:

class CMyAxOptCtrl : public COleControl
{


...


   CPen m_pen;
   CBrush m_brush;
};

Em seguida, a função de OnDraw pode ser reescrita como segue:

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

Essa abordagem impede a criação de forma e de escova cada vez que OnDraw é chamado. A melhoria da velocidade ocorre às custas de manter dados adicionais da instância.

Se a propriedade ForeColor ou de BackColor for alterada, a caneta ou a escova precisam ser criadas novamente. Para fazer isso, substitua as funções de membro de OnForeColorChanged e de OnBackColorChanged :

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

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

Finalmente, para eliminar chamadas desnecessários de SelectObject , modifique OnDraw como segue:

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 também

Referência

Classe COleControl

Assistente de controle ActiveX MFC

Conceitos

Controles ActiveX MFC: otimização

Controles ActiveX MFC

Controles ActiveX MFC

Controles ActiveX MFC: pintando um controle ActiveX