Otimizando controle desenho
Quando um controle é instruído para desenhar a mesmo em um contexto de dispositivo fornecido pelo contêiner, ele normalmente seleciona objetos GDI (como canetas, pincéis e fontes) no contexto de dispositivo, realiza suas operações de desenho e restaura os objetos GDI anteriores.Se o contêiner tem vários controles que estão a ser desenhada no mesmo contexto de dispositivo, e cada controle seleciona objetos GDI requer, tempo pode ser salvas se os controles não restauram objetos anteriormente selecionados individualmente.Após todos os controles foram desenhados, o contêiner pode automaticamente restaurar objetos originais.
Para detectar se um contêiner oferece suporte a essa técnica, um controle pode chamar o COleControl::IsOptimizedDraw função de membro.Se essa função retorna TRUE, o controle pode ignorar a etapa normal de restauração de objetos selecionados anteriormente.
Considere um controle que tem o seguinte (otimizado) OnDraw função:
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);
}
Caneta e Pincel neste exemplo são variáveis locais, significando que os destruidores serão chamados quando saem do escopo (quando o OnDraw função extremidades).Os destruidores tentará excluir objetos GDI correspondentes.Mas eles não devem ser excluídos se você pretende deixar selecionado no contexto de dispositivo no retorno de OnDraw.
Para impedir que o CPen e CBrush objetos sejam destruídos quando OnDraw terminar, armazená-los em variáveis de membro em vez de variáveis locais.Na declaração de classe do controle, adicione declarações de duas novas variáveis de membro:
class CMyAxOptCtrl : public COleControl
{
...
CPen m_pen;
CBrush m_brush;
};
Então, a OnDraw função pode ser reescrita da seguinte maneira:
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 evita a criação de caneta e Pincel sempre OnDraw é chamado.A melhoria de velocidade vem o custo da manutenção dos dados de instância adicional.
Se a propriedade ForeColor ou BackColor for alterado, caneta ou Pincel precisa ser criado novamente.Para fazer isso, substituir o OnForeColorChanged e OnBackColorChanged funções de membro:
void CMyAxOptCtrl::OnForeColorChanged()
{
m_pen.DeleteObject();
}
void CMyAxOptCtrl::OnBackColorChanged()
{
m_brush.DeleteObject();
}
Finalmente, para eliminar desnecessários SelectObject chamadas, modificar OnDraw da seguinte maneira:
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);
}
}