Share via


Graphics Containers

Graphics state clipping region, transformations, and quality settings is stored in a Graphics object. GDI+ allows you to temporarily replace or augment part of the state in a Graphics object by using a container. You start a container by calling the BeginContainer method of a Graphics object, and you end a container by calling the EndContainer method. In between BeginContainer and EndContainer, any state changes you make to the Graphics object belong to the container and do not overwrite the existing state of the Graphics object.

The following example creates a container within a Graphics object. The world transformation of the Graphics object is a translation 200 units to the right, and the world transformation of the container is a translation 100 units down.

myGraphics.TranslateTransform(200, 0)

myGraphicsContainer = myGraphics.BeginContainer()
   myGraphics.TranslateTransform(0, 100)
   myGraphics.DrawRectangle(myPen, 0, 0, 50, 50)
myGraphics.EndContainer(myGraphicsContainer)
myGraphics.DrawRectangle(myPen, 0, 0, 50, 50)
[C#]
myGraphics.TranslateTransform(200, 0);

myGraphicsContainer = myGraphics.BeginContainer();
   myGraphics.TranslateTransform(0, 100);
   myGraphics.DrawRectangle(myPen, 0, 0, 50, 50);
myGraphics.EndContainer(myGraphicsContainer);
myGraphics.DrawRectangle(myPen, 0, 0, 50, 50);

Note that in the preceding example, the statement myGraphics.DrawRectangle(0, 0, 50, 50) made in between the calls to BeginContainer and EndContainer produces a different rectangle than the same statement made after the call to EndContainer. Only the horizontal translation applies to the DrawRectangle call made outside of the container. Both transformations the horizontal translation of 200 units and the vertical translation of 100 units apply to the DrawRectangle call made inside the container. The following illustration shows the two rectangles.

Aa311465.aboutgdip05_art17(en-us,VS.71).gif

Containers can be nested within containers. The following example creates a container within a Graphics object and another container within the first container. The world transformation of the Graphics object is a translation 100 units in the x direction and 80 units in the y direction. The world transformation of the first container is a 30-degree rotation. The world transformation of the second container is a scaling by a factor of 2 in the x direction. A call to the DrawEllipse method is made inside the second container.

myGraphics.TranslateTransform(100, 80, MatrixOrder.Append)

container1 = myGraphics.BeginContainer()
   myGraphics.RotateTransform(30, MatrixOrder.Append)

   container2 = myGraphics.BeginContainer()
      myGraphics.ScaleTransform(2, 1)
      myGraphics.DrawEllipse(myPen, - 30, - 20, 60, 40)
   myGraphics.EndContainer(container2)

myGraphics.EndContainer(container1)
[C#]
myGraphics.TranslateTransform(100, 80, MatrixOrder.Append);

container1 = myGraphics.BeginContainer();
   myGraphics.RotateTransform(30, MatrixOrder.Append);

   container2 = myGraphics.BeginContainer();
      myGraphics.ScaleTransform(2, 1);
      myGraphics.DrawEllipse(myPen, -30, -20, 60, 40);
   myGraphics.EndContainer(container2);

myGraphics.EndContainer(container1);

The following illustration shows the ellipse.

Aa311465.aboutgdip05_art18(en-us,VS.71).gif

Note that all three transformations apply to the DrawEllipse call made in the second container. Also note the order of the transformations: first scale, then rotate, then translate. The innermost transformation is applied first, and the outermost transformation is applied last.

Any property of a Graphics object can be set inside a container (in between calls to BeginContainer and EndContainer). For example, a clipping region can be set inside a container. Any drawing done inside the container will be restricted to the clipping region of that container and will also be restricted to the clipping regions of any outer containers and the clipping region of the Graphics object itself.

The properties discussed so far the world transformation and the clipping region are combined by nested containers. Other properties are temporarily replaced by a nested container. For example, if you set the SmoothingMode property to SmoothingMode.AntiAlias within a container, any drawing methods called inside that container will use the AntiAlias smoothing mode, but drawing methods called after EndContainer will use the smoothing mode that was in place before the call to BeginContainer.

For another example of combining the world transformations of a Graphics object and a container, suppose you want to draw an eye and place it at various locations on a sequence of faces. The following example draws an eye centered at the origin of the coordinate system:

Private Sub DrawEye(myGraphics As Graphics)
   Dim eyeContainer As GraphicsContainer
      
   eyeContainer = myGraphics.BeginContainer()
      
      Dim myBlackPen As New Pen(Color.Black)
      Dim myGreenBrush As New SolidBrush(Color.Green)
      Dim myBlackBrush As New SolidBrush(Color.Black)
      
      Dim myTopPath As New GraphicsPath()
      myTopPath.AddEllipse(- 30, - 50, 60, 60)
      
      Dim myBottomPath As New GraphicsPath()
      myBottomPath.AddEllipse(- 30, - 10, 60, 60)
      
      Dim myTopRegion As New [Region](myTopPath)
      Dim myBottomRegion As New [Region](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.
      myGraphics.Clip = myTopRegion
      myGraphics.DrawPath(myBlackPen, myBottomPath)
      myGraphics.Clip = myBottomRegion
      myGraphics.DrawPath(myBlackPen, myTopPath)
      
      ' Fill the iris.
      ' The iris is clipped by the bottom ellipse.
      myGraphics.FillEllipse(myGreenBrush, - 10, - 15, 20, 22)
      
      ' Fill the pupil.
      myGraphics.FillEllipse(myBlackBrush, - 3, - 7, 6, 9)
      
   myGraphics.EndContainer(eyeContainer)
End Sub 'DrawEye
[C#]
private void DrawEye(Graphics myGraphics)
{
   GraphicsContainer eyeContainer;

   eyeContainer = myGraphics.BeginContainer();

      Pen myBlackPen = new Pen(Color.Black);
      SolidBrush myGreenBrush = new SolidBrush(Color.Green);
      SolidBrush myBlackBrush = new SolidBrush(Color.Black);

      GraphicsPath myTopPath = new GraphicsPath();
      myTopPath.AddEllipse(-30, -50, 60, 60);

      GraphicsPath myBottomPath = new GraphicsPath();
      myBottomPath.AddEllipse(-30, -10, 60, 60);

      Region myTopRegion = new Region(myTopPath);
      Region myBottomRegion = new Region(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.
      myGraphics.Clip = myTopRegion;
      myGraphics.DrawPath(myBlackPen, myBottomPath);
      myGraphics.Clip = myBottomRegion;
      myGraphics.DrawPath(myBlackPen, myTopPath);

      // Fill the iris.
      // The iris is clipped by the bottom ellipse.
      myGraphics.FillEllipse(myGreenBrush, -10, -15, 20, 22);

      // Fill the pupil.
      myGraphics.FillEllipse(myBlackBrush, -3, -7, 6, 9);

   myGraphics.EndContainer(eyeContainer);
}

The following illustration shows the eye and the coordinate axes.

Aa311465.aboutgdip05_art19(en-us,VS.71).gif

The DrawEye function in the preceding example receives a Graphics object and immediately creates a container within that Graphics object. This container insulates any code that calls the DrawEye function from property settings made during the execution of the DrawEye function. For example, code in the DrawEye function sets the clipping region of the Graphics object, but when DrawEye returns control to the calling routine, the clipping region will be as it was before the call to DrawEye.

The following example draws three ellipses (faces), each with an eye inside:

' Draw an ellipse centered at (100, 100).
myGraphics.TranslateTransform(100, 100)
myGraphics.DrawEllipse(myBlackPen, - 40, - 60, 80, 120)

' Draw the eye at the center of the ellipse.
DrawEye(myGraphics)

' Draw an ellipse centered at 200, 100.
myGraphics.TranslateTransform(100, 0, MatrixOrder.Append)
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)
   myGraphics.TranslateTransform(0, - 30, MatrixOrder.Append)
   DrawEye(myGraphics)
myGraphics.EndContainer(myGraphicsContainer)
      
' Draw an ellipse centered at (300, 100).
myGraphics.TranslateTransform(100, 0, MatrixOrder.Append)
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, 1.5F)
   myGraphics.RotateTransform(45, MatrixOrder.Append)
   DrawEye(myGraphics)
myGraphics.EndContainer(myGraphicsContainer)
[C#]
// Draw an ellipse centered at (100, 100).
myGraphics.TranslateTransform(100, 100);
myGraphics.DrawEllipse(myBlackPen, -40, -60, 80, 120);

// Draw the eye at the center of the ellipse.
DrawEye(myGraphics);

// Draw an ellipse centered at 200, 100.
myGraphics.TranslateTransform(100, 0, MatrixOrder.Append);
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);
   myGraphics.TranslateTransform(0, -30, MatrixOrder.Append);
   DrawEye(myGraphics);
myGraphics.EndContainer(myGraphicsContainer);

// Draw an ellipse centered at (300, 100).
myGraphics.TranslateTransform(100, 0, MatrixOrder.Append);
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, 1.5f);
   myGraphics.RotateTransform(45, MatrixOrder.Append);
   DrawEye(myGraphics);
myGraphics.EndContainer(myGraphicsContainer);

The following illustration shows the three ellipses.

Aa311465.aboutgdip05_art20(en-us,VS.71).gif

In the preceding example, all ellipses are drawn with the call DrawEllipse(myBlackPen, -40, -60, 80, 120), which draws an ellipse centered at the origin of the coordinate system. The ellipses are moved away from the upper-left corner of the client area by setting the world transformation of the Graphics object. The statement myGraphics.TranslateTransform(100, 100) causes the first ellipse to be centered at (100, 100). The statement myGraphics.TranslateTransform(100, 0) causes the center of the second ellipse to be 100 units to the right of the center of the first ellipse. Likewise, the center of the third ellipse is 100 units to the right of the center of the second ellipse.

The containers in the preceding example are used to transform the eye relative to the center of a given ellipse. The first eye is drawn at the center of the ellipse with no transformation, so the DrawEye call is not inside a container. The second eye is rotated 40 degrees and drawn 30 units above the center of the ellipse, so the DrawEye function and the methods that set the transformation are called inside a container. The third eye is stretched and rotated and drawn at the center of the ellipse. As with the second eye, the DrawEye function and the methods that set the transformation are called inside a container.