Contêineres de elementos gráficos
O estado gráfico — região de recorte, transformações e configurações de qualidade — é armazenado em um objeto Graphics . O Windows GDI+ permite que você substitua ou aumente temporariamente parte do estado em um objeto Graphics usando um contêiner. Você inicia um contêiner chamando o método Graphics::BeginContainer de um objeto Graphics e encerra um contêiner chamando o método Graphics::EndContainer . Entre Graphics::BeginContainer e Graphics::EndContainer, todas as alterações de estado feitas no objeto Graphics pertencem ao contêiner e não substituem o estado existente do objeto Graphics .
O exemplo a seguir cria um contêiner dentro de um objeto Graphics . A transformação mundial do objeto Graphics é uma tradução de 200 unidades para a direita, e a transformação mundial do contêiner é uma conversão de 100 unidades para baixo.
myGraphics.TranslateTransform(200.0f, 0.0f);
myGraphicsContainer = myGraphics.BeginContainer();
myGraphics.TranslateTransform(0.0f, 100.0f);
myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50);
myGraphics.EndContainer(myGraphicsContainer);
myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50);
Observe que, no exemplo anterior, a instrução myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50)
feita entre as chamadas para Graphics::BeginContainer e Graphics::EndContainer produz um retângulo diferente da mesma instrução feita após a chamada para Graphics::EndContainer. Somente a tradução horizontal se aplica à chamada DrawRectangle feita fora do contêiner. Ambas as transformações — a tradução horizontal de 200 unidades e a tradução vertical de 100 unidades — se aplicam à chamada Graphics::D rawRectangle feita dentro do contêiner. A ilustração a seguir mostra os dois retângulos.
Os contêineres podem ser aninhados em contêineres. O exemplo a seguir cria um contêiner dentro de um objeto Graphics e outro contêiner dentro do primeiro contêiner. 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 mundial do primeiro contêiner é uma rotação de 30 graus. A transformação mundial do segundo contêiner é um dimensionamento por um fator de 2 na direção x. Uma chamada para o método Graphics::D rawEllipse é feita dentro do segundo contêiner.
myGraphics.TranslateTransform(100.0f, 80.0f, MatrixOrderAppend);
container1 = myGraphics.BeginContainer();
myGraphics.RotateTransform(30.0f, MatrixOrderAppend);
container2 = myGraphics.BeginContainer();
myGraphics.ScaleTransform(2.0f, 1.0f);
myGraphics.DrawEllipse(&myPen, -30, -20, 60, 40);
myGraphics.EndContainer(container2);
myGraphics.EndContainer(container1);
A ilustração a seguir mostra a elipse.
Observe que todas as três transformações se aplicam à chamada Graphics::D rawEllipse feita no segundo contêiner (interno). Observe também a ordem das transformações: primeiro dimensione, depois gire e, em seguida, converta. A transformação mais interna é aplicada primeiro e a transformação mais externa é aplicada por último.
Qualquer propriedade de um objeto Graphics pode ser definida dentro de um contêiner (entre chamadas para Graphics::BeginContainer e Graphics::EndContainer). Por exemplo, uma região de recorte pode ser definida dentro de um contêiner. Qualquer desenho feito dentro do contêiner será restrito à região de recorte desse contêiner e também será restrito às regiões de recorte de todos os contêineres externos e à região de recorte do próprio objeto Graphics .
As propriedades discutidas até agora — a transformação mundial e a região de recorte — são combinadas por contêineres aninhados. Outras propriedades são temporariamente substituídas por um contêiner aninhado. Por exemplo, se você definir o modo de suavização como SmoothingModeAntiAlias em um contêiner, todos os métodos de desenho chamados dentro desse contêiner usarão o modo de suavização antialias, mas os métodos de desenho chamados após Graphics::EndContainer usarão o modo de suavização que estava em vigor antes da chamada para Graphics::BeginContainer.
Para outro exemplo de combinação das transformações mundiais de um objeto Graphics e um contêiner, suponha que você queira chamar a atenção e colocá-lo em vários locais em uma sequência de rostos. O exemplo a seguir desenha um olho centralizado na origem do sistema de coordenadas.
void DrawEye(Graphics* pGraphics)
{
GraphicsContainer eyeContainer;
eyeContainer = pGraphics->BeginContainer();
Pen myBlackPen(Color(255, 0, 0, 0));
SolidBrush myGreenBrush(Color(255, 0, 128, 0));
SolidBrush myBlackBrush(Color(255, 0, 0, 0));
GraphicsPath myTopPath;
myTopPath.AddEllipse(-30, -50, 60, 60);
GraphicsPath myBottomPath;
myBottomPath.AddEllipse(-30, -10, 60, 60);
Region myTopRegion(&myTopPath);
Region myBottomRegion(&myBottomPath);
// Draw the outline of the eye.
// The outline of the eye consists of two ellipses.
// The top ellipse is clipped by the bottom ellipse, and
// the bottom ellipse is clipped by the top ellipse.
pGraphics->SetClip(&myTopRegion);
pGraphics->DrawPath(&myBlackPen, &myBottomPath);
pGraphics->SetClip(&myBottomRegion);
pGraphics->DrawPath(&myBlackPen, &myTopPath);
// Fill the iris.
// The iris is clipped by the bottom ellipse.
pGraphics->FillEllipse(&myGreenBrush, -10, -15, 20, 22);
// Fill the pupil.
pGraphics->FillEllipse(&myBlackBrush, -3, -7, 6, 9);
pGraphics->EndContainer(eyeContainer);
}
A ilustração a seguir mostra o olho e os eixos de coordenadas.
A função DrawEye, definida no exemplo anterior, recebe o endereço de um objeto Graphics e cria imediatamente um contêiner dentro desse objeto Graphics . Esse contêiner isola qualquer código que chame a função DrawEye das configurações de propriedade feitas durante a execução da função DrawEye. Por exemplo, o código na função DrawEye define a região de recorte do objeto Graphics , mas quando DrawEye retorna o controle para a rotina de chamada, a região de recorte será como era antes da chamada para DrawEye.
O exemplo a seguir desenha três reticências (faces), cada uma com um olho dentro.
// Draw an ellipse with center at (100, 100).
myGraphics.TranslateTransform(100.0f, 100.0f);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);
// Draw the eye at the center of the ellipse.
DrawEye(&myGraphics);
// Draw an ellipse with center at 200, 100.
myGraphics.TranslateTransform(100.0f, 0.0f, MatrixOrderAppend);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);
// Rotate the eye 40 degrees, and draw it 30 units above
// the center of the ellipse.
myGraphicsContainer = myGraphics.BeginContainer();
myGraphics.RotateTransform(-40.0f);
myGraphics.TranslateTransform(0.0f, -30.0f, MatrixOrderAppend);
DrawEye(&myGraphics);
myGraphics.EndContainer(myGraphicsContainer);
// Draw a ellipse with center at (300.0f, 100.0f).
myGraphics.TranslateTransform(100.0f, 0.0f, MatrixOrderAppend);
myGraphics.DrawEllipse(&myBlackPen, -40, -60, 80, 120);
// Stretch and rotate the eye, and draw it at the
// center of the ellipse.
myGraphicsContainer = myGraphics.BeginContainer();
myGraphics.ScaleTransform(2.0f, 1.5f);
myGraphics.RotateTransform(45.0f, MatrixOrderAppend);
DrawEye(&myGraphics);
myGraphics.EndContainer(myGraphicsContainer);
A ilustração a seguir mostra as três reticências.
No exemplo anterior, todas as reticências são desenhadas com a chamada DrawEllipse(&myBlackPen, -40, -60, 80, 120)
, que desenha uma elipse centralizada na origem do sistema de coordenadas. As reticências são movidas para longe do canto superior esquerdo da área do cliente definindo a transformação mundial do objeto Graphics . A instrução faz com que a primeira elipse seja centralizada em (100, 100). A instrução faz com que o centro da segunda elipse seja de 100 unidades à direita do centro da primeira elipse. Da mesma forma, o centro da terceira elipse é de 100 unidades à direita do centro da segunda elipse.
Os contêineres no exemplo anterior são usados para transformar o olho em relação ao centro de uma determinada elipse. O primeiro olho é desenhado no centro da elipse sem transformação, portanto, a chamada DrawEye não está dentro de um contêiner. O segundo olho é girado 40 graus e desenhado 30 unidades acima do centro da elipse, de modo que a função DrawEye e os métodos que definem a transformação são chamados dentro de um contêiner. O terceiro olho é estendido e girado e desenhado no centro da elipse. Assim como no segundo olho, a função DrawEye e os métodos que definem a transformação são chamados dentro de um contêiner.