Share via


Utilizar contenedores de gráficos anidados

GDI+ proporciona contenedores que puede usar para reemplazar o aumentar temporalmente parte del estado en un objeto Graphics. Para crear un contenedor, llame al método BeginContainer de un objeto Graphics. Puede llamar a BeginContainer repetidamente a para formar contenedores anidados. Cada llamada a BeginContainer debe emparejarse con una llamada a EndContainer.

Transformaciones en contenedores anidados

En el ejemplo siguiente se crea un objeto Graphics y un contenedor dentro de ese objeto Graphics. La transformación global del objeto Graphics es una traslación de 100 unidades en la dirección x y 80 unidades en la dirección y. La transformación global del contenedor es una rotación de 30 grados. El código realiza la llamada DrawRectangle(pen, -60, -30, 120, 60) dos veces. La primera llamada a DrawRectangle está dentro del contenedor; es decir, la llamada está entre las llamadas a BeginContainer y EndContainer. La segunda llamada a DrawRectangle es después de la llamada a EndContainer.

Graphics graphics = e.Graphics;
Pen pen = new Pen(Color.Red);
GraphicsContainer graphicsContainer;
graphics.FillRectangle(Brushes.Black, 100, 80, 3, 3);

graphics.TranslateTransform(100, 80);

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

graphics.DrawRectangle(pen, -60, -30, 120, 60);
Dim graphics As Graphics = e.Graphics
Dim pen As New Pen(Color.Red)
Dim graphicsContainer As GraphicsContainer
graphics.FillRectangle(Brushes.Black, 100, 80, 3, 3)

graphics.TranslateTransform(100, 80)

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

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

En el código anterior, el rectángulo dibujado desde dentro del contenedor se transforma primero por la transformación global del contenedor (rotación) y, a continuación, por la transformación global del objeto Graphics (traslación). El rectángulo dibujado desde fuera del contenedor solo se transforma mediante la transformación global del objeto Graphics (traslación). En la siguiente ilustración se muestran los dos rectángulos:

Ilustración que muestra contenedores anidados.

Recorte en contenedores anidados

En el ejemplo siguiente se muestra cómo los contenedores anidados controlan las regiones de recorte. El código crea un objeto Graphics y un contenedor dentro de ese objeto Graphics. La región de recorte del Graphics objeto es un rectángulo y la región de recorte del contenedor es una elipse. El código realiza dos llamadas al método DrawLine. La primera llamada a DrawLine está dentro del contenedor y la segunda llamada a DrawLine está fuera del contenedor (después de la llamada a EndContainer). La primera línea se recorta mediante la intersección de las dos zonas de recorte. La segunda línea solo se recorta mediante la región de recorte rectangular del objeto Graphics.

Graphics graphics = e.Graphics;
GraphicsContainer graphicsContainer;
Pen redPen = new Pen(Color.Red, 2);
Pen bluePen = new Pen(Color.Blue, 2);
SolidBrush aquaBrush = new SolidBrush(Color.FromArgb(255, 180, 255, 255));
SolidBrush greenBrush = new SolidBrush(Color.FromArgb(255, 150, 250, 130));

graphics.SetClip(new Rectangle(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 = new GraphicsPath();
path.AddEllipse(75, 50, 100, 150);

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

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

graphics.DrawLine(bluePen, 70, 0, 370, 300);
Dim graphics As Graphics = e.Graphics
Dim graphicsContainer As GraphicsContainer
Dim redPen As New Pen(Color.Red, 2)
Dim bluePen As New Pen(Color.Blue, 2)
Dim aquaBrush As New SolidBrush(Color.FromArgb(255, 180, 255, 255))
Dim greenBrush As New SolidBrush(Color.FromArgb(255, 150, 250, 130))

graphics.SetClip(New Rectangle(50, 65, 150, 120))
graphics.FillRectangle(aquaBrush, 50, 65, 150, 120)

graphicsContainer = graphics.BeginContainer()
' Create a path that consists of a single ellipse.
Dim path As New GraphicsPath()
path.AddEllipse(75, 50, 100, 150)

' Construct a region based on the path.
Dim [region] As New [Region](path)
graphics.FillRegion(greenBrush, [region])

graphics.SetClip([region], CombineMode.Replace)
graphics.DrawLine(redPen, 50, 0, 350, 300)
graphics.EndContainer(graphicsContainer)

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

En la siguiente ilustración se muestran dos líneas recortadas:

Ilustración que muestra un contenedor anidado con líneas recortadas.

Como se muestran en los dos ejemplos anteriores, las transformaciones y las zonas de recorte se acumulan en contenedores anidados. Si establece las transformaciones globales del contenedor y el objeto Graphics, ambas transformaciones se aplicarán a los elementos extraídos desde dentro del contenedor. La transformación del contenedor se aplicará primero y la transformación del objeto Graphics se aplicará en segundo lugar. Si establece las zonas de recorte del contenedor y el objeto Graphics, los elementos extraídos desde dentro del contenedor se recortarán mediante la intersección de las dos zonas de recorte.

Configuración de calidad en contenedores anidados

La configuración de calidad (SmoothingMode, TextRenderingHint y similares) en contenedores anidados no es acumulativa; en su lugar, la configuración de calidad del contenedor reemplaza temporalmente la configuración de calidad de un objeto Graphics. Al crear un contenedor, la configuración de calidad de ese contenedor se establece en los valores predeterminados. Por ejemplo, supongamos que tiene un objeto Graphics con un modo de suavizado de AntiAlias. Al crear un contenedor, el modo de suavizado dentro del contenedor es el modo de suavizado predeterminado. Puede establecer el modo de suavizado del contenedor y los elementos extraídos desde dentro de este se dibujarán según el modo establecido. Los elementos dibujados después de la llamada a EndContainer se dibujarán según el modo de suavizado (AntiAlias) que estaba en su lugar antes de la llamada a BeginContainer.

Varias capas de contenedores anidados

No está limitado a un contenedor en un objeto Graphics. Puede crear una secuencia de contenedores, cada uno anidado en el anterior, y puede especificar la transformación global, la zona de recorte y la configuración de calidad de cada uno de esos contenedores anidados. Si llama a un método de dibujo desde dentro del contenedor más interno, las transformaciones se aplicarán en orden, empezando por el contenedor más interno y finalizando con el contenedor más externo. Los elementos dibujados desde dentro del contenedor más interno se recortarán mediante la intersección de todas las zonas de recorte.

En el ejemplo siguiente se crea un objeto Graphics y se establece su sugerencia de representación de texto en AntiAlias. El código crea dos contenedores, uno anidado dentro del otro. La sugerencia de representación de texto del contenedor externo se establece en SingleBitPerPixel y la sugerencia de representación de texto del contenedor interno se establece en AntiAlias. El código dibuja tres cadenas: una del contenedor interno, otra del contenedor externo y otra del propio objeto Graphics.

Graphics graphics = e.Graphics;
GraphicsContainer innerContainer;
GraphicsContainer outerContainer;
SolidBrush brush = new SolidBrush(Color.Blue);
FontFamily fontFamily = new FontFamily("Times New Roman");
Font font = new Font(fontFamily, 36, FontStyle.Regular, GraphicsUnit.Pixel);

graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

outerContainer = graphics.BeginContainer();

graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;

innerContainer = graphics.BeginContainer();
graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
graphics.DrawString(
   "Inner Container",
   font,
   brush,
   new PointF(20, 10));
graphics.EndContainer(innerContainer);

graphics.DrawString(
   "Outer Container",
   font,
   brush,
   new PointF(20, 50));

graphics.EndContainer(outerContainer);

graphics.DrawString(
   "Graphics Object",
   font,
   brush,
   new PointF(20, 90));
Dim graphics As Graphics = e.Graphics
Dim innerContainer As GraphicsContainer
Dim outerContainer As GraphicsContainer
Dim brush As New SolidBrush(Color.Blue)
Dim fontFamily As New FontFamily("Times New Roman")
Dim font As New Font( _
   fontFamily, _
   36, _
   FontStyle.Regular, _
   GraphicsUnit.Pixel)

graphics.TextRenderingHint = _
System.Drawing.Text.TextRenderingHint.AntiAlias

outerContainer = graphics.BeginContainer()

graphics.TextRenderingHint = _
    System.Drawing.Text.TextRenderingHint.SingleBitPerPixel

innerContainer = graphics.BeginContainer()
graphics.TextRenderingHint = _
    System.Drawing.Text.TextRenderingHint.AntiAlias
graphics.DrawString( _
   "Inner Container", _
   font, _
   brush, _
   New PointF(20, 10))
graphics.EndContainer(innerContainer)

graphics.DrawString("Outer Container", font, brush, New PointF(20, 50))

graphics.EndContainer(outerContainer)

graphics.DrawString("Graphics Object", font, brush, New PointF(20, 90))

En la siguiente ilustración se muestran las tres cadenas. Las cadenas extraídas del contenedor interno y del objeto Graphics se suavizan mediante suavizado de contorno. La cadena dibujada desde el contenedor externo no se suaviza mediante suavizado de contorno debido a que la propiedad TextRenderingHint está establecida en SingleBitPerPixel.

Ilustración que muestra las cadenas extraídas de contenedores anidados.

Consulte también