Compartilhar via


Contêineres de elementos gráficos aninhados

O Windows GDI+ fornece contêineres que você pode usar para substituir ou aumentar temporariamente parte do estado em um objeto Graphics . Você cria um contêiner chamando o método Graphics::BeginContainer de um objeto Graphics . Você pode chamar Graphics::BeginContainer repetidamente para formar contêineres aninhados.

Transformações em contêineres aninhados

O exemplo a seguir cria um objeto Graphics e um contêiner dentro desse objeto Graphics . A transformação mundial do objeto Graphics é uma tradução de 100 unidades na direção x e 80 unidades na direção y. A transformação global do contêiner é uma rotação de 30 graus. O código faz a chamada

DrawRectangle(&pen, -60, -30, 120, 60)

Duas vezes. A primeira chamada para Graphics::D rawRectangle está dentro do contêiner; ou seja, a chamada está entre as chamadas para Graphics::BeginContainer e Graphics::EndContainer. A segunda chamada para Graphics::D rawRectangle é após a chamada para Graphics::EndContainer.

Graphics           graphics(hdc);
Pen                pen(Color(255, 255, 0, 0));
GraphicsContainer  graphicsContainer;

graphics.TranslateTransform(100.0f, 80.0f);

graphicsContainer = graphics.BeginContainer();
   graphics.RotateTransform(30.0f);
   graphics.DrawRectangle(&pen, -60, -30, 120, 60);
graphics.EndContainer(graphicsContainer);

graphics.DrawRectangle(&pen, -60, -30, 120, 60);

No código anterior, o retângulo extraído de dentro do contêiner é transformado primeiro pela transformação mundial do contêiner (rotação) e, em seguida, pela transformação mundial do objeto Graphics (tradução). O retângulo extraído de fora do contêiner é transformado apenas pela transformação mundial do objeto Graphics (tradução). A ilustração a seguir mostra os dois retângulos.

captura de tela de uma janela com dois retângulos vermelhos centralizados no mesmo ponto, mas com rotações diferentes

 

Recorte em contêineres aninhados

O exemplo a seguir ilustra como os contêineres aninhados lidam com regiões de recorte. O código cria um objeto Graphics e um contêiner dentro desse objeto Graphics . A região de recorte do objeto Graphics é um retângulo e a região de recorte do contêiner é uma elipse. O código faz duas chamadas para o método Graphics::D rawLine . A primeira chamada para Graphics::D rawLine está dentro do contêiner e a segunda chamada para Graphics::D rawLine está fora do contêiner (após a chamada para Graphics::EndContainer). A primeira linha é recortada pela interseção das duas áreas de recorte. A segunda linha é recortada apenas pela região de recorte retangular do objeto Graphics .

Graphics           graphics(hdc);
GraphicsContainer  graphicsContainer;
Pen                redPen(Color(255, 255, 0, 0), 2);
Pen                bluePen(Color(255, 0, 0, 255), 2);
SolidBrush         aquaBrush(Color(255, 180, 255, 255));
SolidBrush         greenBrush(Color(255, 150, 250, 130));

graphics.SetClip(Rect(50, 65, 150, 120));
graphics.FillRectangle(&aquaBrush, 50, 65, 150, 120);

graphicsContainer = graphics.BeginContainer();
   // Create a path that consists of a single ellipse.
   GraphicsPath path;
   path.AddEllipse(75, 50, 100, 150);

  // Construct a region based on the path.
   Region region(&path);
   graphics.FillRegion(&greenBrush, &region);

   graphics.SetClip(&region);
   graphics.DrawLine(&redPen, 50, 0, 350, 300);
graphics.EndContainer(graphicsContainer);

graphics.DrawLine(&bluePen, 70, 0, 370, 300);

A ilustração a seguir mostra as duas linhas recortadas.

ilustração de uma elipse dentro de um retângulo, com uma linha recortada pela elipse e a outra pelo retângulo

Como os dois exemplos anteriores mostram, as transformações e áreas de recorte são cumulativas em contêineres aninhados. Se você definir as transformações mundiais do contêiner e o objeto Graphics , ambas as transformações serão aplicadas a itens extraídos de dentro do contêiner. A transformação do contêiner será aplicada primeiro e a transformação do objeto Graphics será aplicada em segundo lugar. Se você definir as regiões de recorte do contêiner e do objeto Graphics , os itens extraídos de dentro do contêiner serão recortados pela interseção das duas regiões de recorte.

Configurações de qualidade em contêineres aninhados

As configurações de qualidade ( SmoothingMode, TextRenderingHint e similares) em contêineres aninhados não são cumulativas; em vez disso, as configurações de qualidade do contêiner substituem temporariamente as configurações de qualidade de um objeto Graphics . Quando você cria um novo contêiner, as configurações de qualidade do contêiner são definidas com valores padrão. Por exemplo, suponha que você tenha um objeto Graphics com um modo de suavização de SmoothingModeAntiAlias. Quando você cria um contêiner, o modo de suavização dentro do contêiner é o modo de suavização padrão. Você tem a liberdade de definir o modo de suavização do contêiner e os itens desenhados de dentro do contêiner serão desenhados de acordo com o modo é definido por você. Os itens desenhados após a chamada para Graphics::EndContainer serão desenhados de acordo com o modo de suavização (SmoothingModeAntiAlias) que estava em vigor antes da chamada para Graphics::BeginContainer.

Várias camadas de contêineres aninhados

Você não está limitado a um contêiner em um objeto Graphics . É possível criar uma sequência de contêineres, cada um deles aninhado no anterior e é possível especificar a transformação global, a área de recorte e as configurações de qualidade de cada um desses contêineres aninhados. Se você chamar um método de desenho de dentro do contêiner mais interno, as transformações serão aplicadas em ordem, começando pelo contêiner mais interno e terminando com mais externo. Itens desenhados de dentro do contêiner mais interno serão recortados pela interseção de todas as áreas de recorte.

O exemplo a seguir cria um objeto Graphics e define sua dica de renderização de texto como TextRenderingHintAntiAlias. O código cria dois contêineres, um aninhado dentro do outro. A dica de renderização de texto do contêiner externo é definida como TextRenderingHintSingleBitPerPixel e a dica de renderização de texto do contêiner interno é definida como TextRenderingHintAntiAlias. O código desenha três cadeias de caracteres: uma do contêiner interno, uma do contêiner externo e outra do próprio objeto Graphics .

Graphics graphics(hdc);
GraphicsContainer innerContainer;
GraphicsContainer outerContainer;
SolidBrush brush(Color(255, 0, 0, 255));
FontFamily fontFamily(L"Times New Roman");
Font font(&fontFamily, 36, FontStyleRegular, UnitPixel);

graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

outerContainer = graphics.BeginContainer();

   graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);

   innerContainer = graphics.BeginContainer();
      graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
      graphics.DrawString(L"Inner Container", 15, &font,
         PointF(20, 10), &brush);
   graphics.EndContainer(innerContainer);

   graphics.DrawString(L"Outer Container", 15, &font, PointF(20, 50), &brush);

graphics.EndContainer(outerContainer);

graphics.DrawString(L"Graphics Object", 15, &font, PointF(20, 90), &brush);

A ilustração a seguir mostra as três cadeias de caracteres. As cadeias de caracteres extraídas do contêiner interno e do objeto Graphics são suavizadas pela suavização. A cadeia de caracteres extraída do contêiner externo não é suavizada pela suavização devido à configuração TextRenderingHintSingleBitPerPixel.

ilustração de um retângulo que contém a mesma cadeia de caracteres há vezes; apenas os caracteres na primeira e última linhas são suaves