GDI+学习之路8--图形容器

来源:互联网 发布:数据库中注释 编辑:程序博客网 时间:2024/06/08 18:46

       图片状态(裁剪区域、变形、质量设置等)存储于Graphics对象中。GDI+ 允许您采用一个容器临时替换或者扩充一个Graphics对象的状态。调用Graphics对象的BeginContainer方法开始一个容器,直至调用EndContainer方法终止一个容器。在这期间,您对于属于该容器的Graphics对象进行的任何状态改变都不会覆盖掉Graphics对象现存的状态。

下面的例子在一个Graphics对象中创建一个容器。Graphics对象的世界变换是向右平移200个单位,而容器的世界变换是向下平移100个单位。

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

       注意,在前面的例子中, 置于BeginContainerEndContainer调用之间的语句myGraphics.DrawRectangle(&myPen, 0, 0, 50, 50)产生的矩形和EndContainer调用之后的同样的语句产生了不同的2个矩形。应用于DrawRectangle调用的两种变换(水平平移200个单位和垂直平移100个单位)都在容器内部进行。下图显示了这两个矩形。

  

       容器可以与容器嵌套。下面的例子在一个Graphics对象内创建一个容器,紧接着在前一个容器中再创建另一个容器。Graphics容器的世界变换是沿X轴平移100个单位然后沿Y轴平移80个单位。第一个容器的世界变换是旋转30度角。第二个容器的世界变换是沿X轴缩放2倍单位。在第二个容器中调用DrawEllipse方法。

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

注意,所有的变换都应用于第二个(最里面的)容器里面的DrawEllipse调用。同时注意,变换的顺序:首先缩放,然后是旋转,然后才是平移。最内层的变换最先被执行,最外层的变换最迟执行。

在容器内部(在BeginContainerEndContainer调用之间)可以对Graphics对象的任意属性进行设置。例如,可以在容器内设置一个剪切区域。容器内的任何绘图操作都将被该容器的剪切区域所裁剪,同时也会被外层容器以及Graphics对象本身的剪切区域所裁剪。

关于属性的讨论已经很深入了,嵌套容器中的世界变换和裁剪区域。其他属性则由嵌套容器临时替换。例如,当您在一个容器中通过SmoothingModeAntiAlias设置了平滑模式后,在容器内部的任何绘图操作都将采用这个平滑模式,但是在EndContainer调用之后的绘图操作则采用BeginContainer调用之前的平滑模式。

再举个容器内部一个Graphics对象的世界变换的例子,假设立希望绘制一只眼睛然后将它放到若干脸部的不同位置。下面的例子将在坐标系统原点位置绘制一只眼睛。

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 theoutline of the eye.

   // The outline of the eye consists of two ellipses.

  // The topellipse 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 theiris.

  // The iris isclipped by the bottom ellipse.

  pGraphics->FillEllipse(&myGreenBrush, -10, -15, 20, 22);

 

  // Fill thepupil.

  pGraphics->FillEllipse(&myBlackBrush, -3, -7, 6, 9);

 

  pGraphics->EndContainer(eyeContainer);

}

       上面例子中的DrawEye函数接受一个Graphics对象地址,然后立即在该Graphics对象中创建一个容器。容器使得DrawEye函数内部的代码调用与在执行过程中的属性设置相脱离。例如,DrawEys函数内部代码设置了Graphics对象的剪切区域,但是当DrawEys将控制权返回给调用例程后,裁剪区域将恢复为DrawEye调用之前的状态。

下面的代码演示了绘制3个椭圆(脸),每个内部都有一只眼睛。

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

       上例中,所有的椭圆都是采用DrawEllipse(&myBlackPen,-40, -60, 80, 120)调用绘制的,该语句将在坐标系统的原点位置绘制椭圆。通过设置Graphics对象的世界变换来将椭圆的工作区从左上角移开。该语句使得第一个椭圆在(100,100)的位置居中,使得第二个椭圆在第一个椭圆中心位置向右平移了100个单位。同样地,第三个椭圆的中心又在第二个椭圆的基础上向右平移了100个单位。

上例中的容器用于相对于给定椭圆中心对眼睛进行平移。第一只绘制于椭圆中心位置的眼睛没有任何变换,因此没有将DrawEye调用放到容器中。第二只眼睛旋转40度后又相对于椭圆中心向上平移了30个单位,因此DrawEye函数调用和变换等操作是在容器内部进行的。第三个眼睛进行了缩放、旋转操作然后绘制于椭圆中心位置。与第二只眼睛类似的,DrawEye函数调用和变换等操作也是置于容器内部的。

 

原创粉丝点击