使用嵌套的 Graphics 容器

GDI+ 提供可用于在 Graphics 对象中临时替换或增加状态部件的容器。 通过调用 Graphics 对象的 BeginContainer 方法创建容器。 可重复调用 BeginContainer 以形成嵌套容器。 每调用一次 BeginContainer,都要调用一次 EndContainer

嵌套容器中的变换

下面的示例创建一个 Graphics 对象并在该 Graphics 对象中创建一个容器。 Graphics 对象的世界变换是在 x 方向平移 100 个单位,在 y 方向平移 80 个单位。 该容器的世界变换是旋转 30 度。 该代码调用两次 DrawRectangle(pen, -60, -30, 120, 60) 。 对 DrawRectangle 的第一次调用是在容器的内部,也就是说,此调用是在调用 BeginContainerEndContainer 之间发生的。 对 DrawRectangle 的第二次调用是在调用 EndContainer 之后。

        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)

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

在上面的代码中,从容器内部绘制的矩形依次经过容器的世界变换(旋转)和 Graphics 对象的世界变换(平移)。 从容器外部绘制的矩形只经过 Graphics 对象的世界变换(平移)。 下面的插图显示这两个矩形。

嵌套容器

在嵌套容器中剪辑

下面的示例演示嵌套容器如何处理剪辑区域。 该代码创建一个 Graphics 对象并在该 Graphics 对象中创建一个容器。 Graphics 对象的剪辑区域是矩形,容器的剪辑区域是椭圆。 该代码调用两次 DrawLine 方法。 第一次调用 DrawLine 是在容器内部,第二次调用 DrawLine 是在容器的外部(在调用 EndContainer 之后)。 第一条直线被两个剪辑区域的相交部分剪辑。 第二条直线只被 Graphics 对象的矩形剪辑区域剪辑。

        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)

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

下面的插图显示这两条剪辑过的直线。

嵌套容器

正如上面的示例所示,变换和剪辑区域在嵌套容器中是累积的。 如果设置容器和 Graphics 对象的世界变换,则这两种变换都将应用于从容器内部绘制的项目。 首先应用容器的变换,再应用 Graphics 对象的变换。 如果设置容器和 Graphics 对象的剪辑区域,则从容器内部绘制的项目将被两个剪辑区域的相交部分剪辑。

嵌套容器中的品质设置

嵌套容器中的品质设置(SmoothingModeTextRenderingHint 等)是不累积的;相反,容器的品质设置会临时替换 Graphics 对象的品质设置。 在创建新容器时,该容器的品质设置将被设置为默认值。 例如,假设有一个 Graphics 对象,其平滑模式为 AntiAlias。 在创建容器时,容器内部的平滑模式是默认的平滑模式。 您可随意设置该容器的平滑模式,而在容器内部绘制的任何项目将按照您所设置的模式绘制。 在调用 EndContainer 之后绘制的项目,将按照在调用 BeginContainer 之前就已设置好的 (AntiAlias) 平滑模式绘制。

多层嵌套容器

Graphics 对象中,并不限于只有一个容器。 您可创建一系列容器,每个容器都嵌套在前一个容器中;您可为每个嵌套容器指定世界变换、剪辑区域和品质设置。 如果从最里边的容器内部调用绘图方法,则变换将按顺序应用,即,始于最里边的容器,终于最外边的容器。 从最里边的容器内部绘制的项目将被所有剪辑区域的相交部分剪辑。

下面的示例创建 Graphics 对象并将其文本呈现提示设置为 AntiAlias。 该代码创建两个容器,一个嵌套在另一个中。 外部容器和内部容器的文本呈现提示分别设置为 SingleBitPerPixelAntiAlias。 该代码绘制三个字符串:一个从内部容器绘制,另一个从外部容器绘制,第三个从 Graphics 对象本身绘制。

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

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

下面的插图显示这三个字符串。 从内部容器和 Graphics 对象绘制的字符串都由“抗锯齿”平滑。 从外部容器绘制的字符串不由“抗锯齿”平滑,这是由于 TextRenderingHint 属性被设置为 SingleBitPerPixel

嵌套容器

请参见

参考

Graphics

概念

管理 Graphics 对象的状态