Partilhar via


Controles ActiveX MFC: pintando um controle ActiveX

Este artigo descreve o processo de pintura de controle ActiveX e como é possível alterar o código de pintura para otimizar o processo. (Consulte Otimizar o desenho de controle para obter as técnicas sobre como otimizar o desenho sem que os controles restaurem de modo individual os objetos GDI selecionados anteriormente. Depois que todos os controles forem desenhados, o contêiner poderá restaurar automaticamente os objetos originais.)

Importante

O ActiveX é uma tecnologia herdada que não deve ser usada para novo desenvolvimento. Para mais informações sobre tecnologias modernas que substituem o ActiveX, confira Controles do ActiveX.

Os exemplos neste artigo são de um controle criado pelo Assistente de Controle ActiveX do MFC com configurações padrão. Para obter mais informações sobre como criar um aplicativo de controle de esqueleto usando o Assistente de Controle ActiveX do MFC, consulte o artigo Assistente de Controle ActiveX do MFC.

Os seguintes tópicos são abordados:

O processo de pintura de um controle ActiveX

Quando os controles ActiveX são exibidos inicialmente ou redesenhados, eles seguem um processo de pintura semelhante a outros aplicativos desenvolvidos usando MFC, com uma distinção importante: os controles ActiveX poderão estar em um estado ativo ou inativo.

Um controle ativo é representado em um contêiner de controle ActiveX por uma janela filho. Como outras janelas, será responsável por pintar a si mesma quando uma mensagem WM_PAINT for recebida. A classe base do controle, COleControl, trata essa mensagem na função OnPaint. Essa implementação padrão chama a função OnDraw do controle.

Um controle inativo é pintado de forma diferente. Quando o controle estiver inativo, a janela ficará invisível ou inexistente, portanto, não poderá receber uma mensagem de pintura. Em vez disso, o contêiner de controle chama diretamente a função OnDraw do controle. Isso difere do processo de pintura de um controle ativo em que a função membro OnPaint nunca é chamada.

Conforme discutido nos parágrafos anteriores, como um controle ActiveX é atualizado depende do estado do controle. No entanto, como a estrutura chama a função membro OnDraw, em ambos os casos você adicionará a maior parte do código de pintura nessa função membro.

A função membro OnDraw manipula a pintura de controle. Quando um controle está inativo, o contêiner de controle chama OnDraw, passando o contexto de dispositivo do contêiner de controle e as coordenadas da área retangular ocupada pelo controle.

O retângulo passado pela estrutura à função membro OnDraw contém a área ocupada pelo controle. Se o controle estiver ativo, o canto superior esquerdo será (0, 0) e o contexto de dispositivo passado será para a janela filho que contém o controle. Se o controle estiver inativo, a coordenada superior esquerda não será necessariamente (0, 0) e o contexto do dispositivo passado será para o contêiner de controle que contém o controle.

Observação

É importante que as modificações no OnDraw não dependam que o ponto superior esquerdo do retângulo seja igual a (0, 0) e que você desenhe apenas dentro do retângulo passado para o OnDraw. Resultados inesperados poderão ocorrer se você desenhar além da área do retângulo.

A implementação padrão fornecida pelo Assistente de Controle ActiveX do MFC no arquivo de implementação de controle (.CPP), mostrado abaixo, pinta o retângulo com um pincel branco e preenche a elipse com a cor da tela de fundo atual.

void CMyAxUICtrl::OnDraw(CDC* pdc, const CRect& rcBounds, const CRect& /*rcInvalid*/)
{
   if (!pdc)
      return;

   // TODO: Replace the following code with your own drawing code.
   pdc->FillRect(rcBounds, CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH)));
   pdc->Ellipse(rcBounds);
}

Observação

Ao pintar um controle, não faça suposições sobre o estado do contexto do dispositivo que é passado como parâmetro pdc para a função OnDraw. Ocasionalmente, o contexto do dispositivo é fornecido pelo aplicativo de contêiner e não será necessariamente inicializado no estado padrão. Em particular, selecione explicitamente as canetas, os pincéis, as cores, as fontes e outros recursos dos quais o código de desenho depende.

Otimizar o código de pintura

Depois que o controle estiver se pintando com êxito, a próxima etapa será otimizar a função OnDraw.

A implementação padrão da pintura de controle ActiveX pinta toda a área de controle. Isso é suficiente para controles simples, mas, em muitos casos, repintar o controle será mais rápido se apenas a parte que precisa de atualização for repintada, em vez de todo o controle.

A função OnDraw fornece um método fácil de otimização passando rcInvalid, a área retangular do controle a ser redesenhada. Use essa área, geralmente menor que toda a área de controle, para acelerar o processo de pintura.

Pintar o controle usando metarquivos

Na maioria dos casos, o parâmetro pdc para a função OnDraw aponta para um contexto de DC (dispositivo de tela). No entanto, ao imprimir as imagens do controle ou durante uma sessão de visualização de impressão, o DC recebido para renderização será um tipo especial chamado "DC de metarquivo". Ao contrário de um DC de tela, que trata imediatamente de solicitações enviadas a ele, um DC de metarquivo armazena as solicitações que serão reproduzidas posteriormente. Alguns aplicativos de contêiner também poderão optar por renderizar a imagem de controle usando um DC de metarquivo, quando estiver em modo de design.

As solicitações de desenho de metarquivo poderão ser feitas pelo contêiner por meio de duas funções de interface: IViewObject::Draw (essa função também pode ser chamada para desenho não metarquivo) e IDataObject::GetData. Quando um DC de metarquivo é passado como um dos parâmetros, a estrutura do MFC faz uma chamada para COleControl::OnDrawMetafile. Como essa é uma função membro virtual, substitua essa função na classe de controle para fazer qualquer processamento especial. O comportamento padrão chama COleControl::OnDraw.

Para garantir que o controle poderá ser desenhado em contextos de dispositivo de tela e metarquivo, use apenas funções membro com suporte em uma tela e um DC de metarquivo. Lembre-se de que o sistema de coordenadas não pode ser medido em pixels.

Como a implementação padrão de OnDrawMetafile chama a função OnDraw, use apenas funções membro adequadas tanto para um contexto de dispositivo de tela quanto de metarquivo, a menos que você substitua OnDrawMetafile. A seguir, lista o subconjunto de funções membro do CDC que podem ser usadas em um contexto de dispositivo de tela e em um de metarquivo. Para obter mais informações sobre essas funções, consulte a classe CDC na Referência do MFC.

Arc BibBlt Acorde
Ellipse Escape ExcludeClipRect
ExtTextOut FloodFill IntersectClipRect
LineTo MoveTo OffsetClipRgn
OffsetViewportOrg OffsetWindowOrg PatBlt
Pie Polygon Polyline
PolyPolygon RealizePalette RestoreDC
RoundRect SaveDC ScaleViewportExt
ScaleWindowExt SelectClipRgn SelectObject
SelectPalette SetBkColor SetBkMode
SetMapMode SetMapperFlags SetPixel
SetPolyFillMode SetROP2 SetStretchBltMode
SetTextColor SetTextJustification SetViewportExt
SetViewportOrg SetWindowExt SetWindowORg
StretchBlt TextOut

Além das funções membro de CDC, há várias outras funções compatíveis em um DC de metarquivo. Essas incluem CPalette::AnimatePalette, CFont::CreateFontIndirect e três funções membro de CBrush: CreateBrushIndirect, CreateDIBPatternBrush, and CreatePatternBrush.

As funções que não são registradas em um metarquivo são: DrawFocusRect, DrawIcon, DrawText, ExcludeUpdateRgn, FillRect, FrameRect, GrayString, InvertRect, ScrollDC e TabbedTextOut. Como um DC de metarquivo não é realmente associado a um dispositivo, não é possível usar SetDIBits, GetDIBits e CreateDIBitmap com um DC de metarquivo. É possível usar SetDIBitsToDevice e StretchDIBits com um DC de metarquivo como o destino. CreateCompatibleDC, CreateCompatibleBitmap e CreateDiscardableBitmap não são significativos com um DC de metarquivo.

Outro ponto a ser considerado ao usar um DC de metarquivo é que o sistema de coordenadas não pode ser medido em pixels. Por esse motivo, todo o código de desenho deverá ser adaptado para ajustar no retângulo passado para OnDraw no parâmetro rcBounds. Isso evitará a pintura acidental fora do controle porque rcBounds representa o tamanho da janela do controle.

Após implementar a renderização de metarquivo para o controle, use o Contêiner de Teste para testar o metarquivo. Confira Testar Propriedades e Eventos com o Contêiner de Testes para obter informações sobre como acessar o contêiner de testes.

Testar o metarquivo do controle usando o Contêiner de Teste

  1. No menu Editar do Contêiner de Teste, clique em Inserir Novo Controle.

  2. Na caixa Inserir Novo Controle, selecione o controle e clique em OK.

    O controle aparecerá no contêiner de teste.

  3. No menu Controle, clique em Desenhar Metarquivo.

    Uma janela separada aparecera na qual o metarquivo será exibido. É possível alterar o tamanho dessa janela para ver como o dimensionamento afetará o metarquivo do controle. Você poderá fechar essa janela a qualquer momento.

Confira também

Controles ActiveX do MFC