Contenedores de gráficos

El estado de los gráficos ( región de recorte, transformaciones y configuración de calidad) se almacena en un objeto Graphics . Windows GDI+ permite reemplazar o aumentar temporalmente parte del estado en un objeto Graphics mediante un contenedor. Para iniciar un contenedor, llame al método Graphics::BeginContainer de un objeto Graphics y finalice un contenedor llamando al método Graphics::EndContainer . Entre Graphics::BeginContainer y Graphics::EndContainer, los cambios de estado realizados en el objeto Graphics pertenecen al contenedor y no sobrescriben el estado existente del objeto Graphics .

En el ejemplo siguiente se crea un contenedor dentro de un objeto Graphics . La transformación mundial del objeto Graphics es una traducción de 200 unidades a la derecha y la transformación mundial del contenedor es una traducción de 100 unidades hacia abajo.

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);

Tenga en cuenta que, en el ejemplo anterior, la instrucción myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50) realizada entre las llamadas a Graphics::BeginContainer y Graphics::EndContainer genera un rectángulo diferente al de la misma instrucción realizada después de la llamada a Graphics::EndContainer. Solo la traducción horizontal se aplica a la llamada DrawRectangle realizada fuera del contenedor. Ambas transformaciones (la traducción horizontal de 200 unidades y la traducción vertical de 100 unidades) se aplican a la llamada Graphics::D rawRectangle realizada dentro del contenedor. En la ilustración siguiente se muestran los dos rectángulos.

captura de pantalla de una ventana con dos rectángulos dibujados con un lápiz azul, uno situado encima del otro

Los contenedores se pueden anidar dentro de contenedores. En el ejemplo siguiente se crea un contenedor dentro de un objeto Graphics y otro contenedor dentro del primer contenedor. La transformación mundial del objeto Graphics es una traducción de 100 unidades en dirección x y 80 unidades en la dirección y. La transformación mundial del primer contenedor es una rotación de 30 grados. La transformación mundial del segundo contenedor es un escalado por un factor de 2 en la dirección x. Se realiza una llamada al método Graphics::D rawEllipse dentro del segundo contenedor.

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);

En la ilustración siguiente se muestra la elipse.

captura de pantalla de una ventana que contiene una elipse azul girada con su centro etiquetado como (100,80)

Tenga en cuenta que las tres transformaciones se aplican a la llamada Graphics::D rawEllipse realizada en el segundo contenedor (más interno). Tenga en cuenta también el orden de las transformaciones: primero escale, luego gire y, a continuación, traduzca. La transformación más interna se aplica primero y la transformación más externa se aplica en último lugar.

Cualquier propiedad de un objeto Graphics se puede establecer dentro de un contenedor (entre llamadas a Graphics::BeginContainer y Graphics::EndContainer). Por ejemplo, una región de recorte se puede establecer dentro de un contenedor. Cualquier dibujo realizado dentro del contenedor se restringirá a la región de recorte de ese contenedor y también se restringirá a las regiones de recorte de cualquier contenedor externo y la región de recorte del propio objeto Graphics .

Las propiedades descritas hasta ahora (la transformación mundial y la región de recorte) se combinan mediante contenedores anidados. Otras propiedades se reemplazan temporalmente por un contenedor anidado. Por ejemplo, si establece el modo de suavizado en SmoothingModeAntiAlias dentro de un contenedor, los métodos de dibujo llamados dentro de ese contenedor usarán el modo de suavizado de suavizado de contornos, pero los métodos de dibujo llamados después de Graphics::EndContainer usarán el modo de suavizado que estaba en su lugar antes de la llamada a Graphics::BeginContainer.

Para otro ejemplo de combinación de las transformaciones del mundo de un objeto Graphics y un contenedor, supongamos que desea dibujar un ojo y colocarlo en varias ubicaciones en una secuencia de caras. En el ejemplo siguiente se dibuja un ojo centrado en el origen del 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);
}

En la ilustración siguiente se muestran el ojo y los ejes de coordenadas.

ilustración en la que se muestra un ojo compuesto de tres puntos suspensivos: uno para el contorno, el iris y la pupila

La función DrawEye, definida en el ejemplo anterior, recibe la dirección de un objeto Graphics y crea inmediatamente un contenedor dentro de ese objeto Graphics . Este contenedor aísla cualquier código que llame a la función DrawEye de la configuración de propiedad realizada durante la ejecución de la función DrawEye. Por ejemplo, el código de la función DrawEye establece la región de recorte del objeto Graphics , pero cuando DrawEye devuelve el control a la rutina de llamada, la región de recorte será como antes de la llamada a DrawEye.

En el ejemplo siguiente se dibujan tres puntos suspensivos (caras), cada uno con un ojo 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);

En la ilustración siguiente se muestran los tres puntos suspensivos.

captura de pantalla de una ventana con tres puntos suspensivos, cada uno de los cuales contiene un ojo con un tamaño y rotación diferentes

En el ejemplo anterior, todos los puntos suspensivos se dibujan con la llamada DrawEllipse(&myBlackPen, -40, -60, 80, 120)a , que dibuja una elipse centrada en el origen del sistema de coordenadas. Los puntos suspensivos se alejan de la esquina superior izquierda del área de cliente estableciendo la transformación mundial del objeto Graphics . La instrucción hace que la primera elipse se centre en (100, 100). La instrucción hace que el centro de la segunda elipse sea de 100 unidades a la derecha del centro de la primera elipse. Del mismo modo, el centro de la tercera elipse es de 100 unidades a la derecha del centro de la segunda elipse.

Los contenedores del ejemplo anterior se usan para transformar el ojo en relación con el centro de una elipse determinada. El primer ojo se dibuja en el centro de la elipse sin transformación, por lo que la llamada DrawEye no está dentro de un contenedor. El segundo ojo gira 40 grados y dibuja 30 unidades encima del centro de la elipse, por lo que la función DrawEye y los métodos que establecen la transformación se llaman dentro de un contenedor. El tercer ojo se estira y gira y dibuja en el centro de la elipse. Al igual que con el segundo ojo, la función DrawEye y los métodos que establecen la transformación se llaman dentro de un contenedor.