嵌套图形容器

Windows GDI+ 提供了可用于临时替换或扩充 Graphics 对象中部分状态的容器。 通过调用 Graphics 对象的 Graphics::BeginContainer 方法创建容器。 可以重复调用 Graphics::BeginContainer 以形成嵌套容器。

嵌套容器中的转换

以下示例在该 Graphics 对象中创建一个 Graphics 对象和一个容器。 Graphics 对象的世界转换是 x 方向的 100 个单位和 80 个单位在 y 方向的平移。 容器的世界转换是 30 度旋转。 代码进行调用

DrawRectangle(&pen, -60, -30, 120, 60)

两次。 对 Graphics::D rawRectangle 的第一次调用位于 容器内;也就是说,调用位于 对 Graphics::BeginContainerGraphics::EndContainer 的调用之间。 第二次调用 Graphics::D rawRectangle 是在调用 Graphics::EndContainer 之后。

Graphics           graphics(hdc);
Pen                pen(Color(255, 255, 0, 0));
GraphicsContainer  graphicsContainer;

graphics.TranslateTransform(100.0f, 80.0f);

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

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

在前面的代码中,从容器内部绘制的矩形首先由容器的世界转换 (旋转) 转换,然后由 Graphics 对象的世界转换 (转换) 进行转换。 从容器外部绘制的矩形仅通过 图形 对象的世界转换 (转换) 进行转换。 下图显示了这两个矩形。

窗口的屏幕截图,其中两个红色矩形居中同一点,但旋转不同

 

嵌套容器中的剪切

以下示例演示嵌套容器如何处理剪辑区域。 该代码会在 该 Graphics 对象中创建一个 Graphics 对象和一个容器。 Graphics 对象的剪裁区域是一个矩形,容器的剪裁区域是一个椭圆。 代码对 Graphics::D rawLine 方法进行两次调用。 第一次调用 Graphics::D rawLine 位于容器内,第二次调用 Graphics::D rawLine 在调用 Graphics::EndContainer) 之后,在容器外部 (。 第一行以两个剪切区域的交集进行剪切。 第二行仅由 Graphics 对象的矩形剪裁区域进行剪裁。

Graphics           graphics(hdc);
GraphicsContainer  graphicsContainer;
Pen                redPen(Color(255, 255, 0, 0), 2);
Pen                bluePen(Color(255, 0, 0, 255), 2);
SolidBrush         aquaBrush(Color(255, 180, 255, 255));
SolidBrush         greenBrush(Color(255, 150, 250, 130));

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

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

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

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

下图显示了两个已剪裁的行。

矩形内椭圆的插图,其中一行由椭圆剪裁,另一行由矩形剪裁

如前两个示例所示,转换和剪切区域在嵌套容器中累积。 如果设置容器和 Graphics 对象的世界转换,这两种转换将应用于从容器内部绘制的项。 首先应用容器的转换,第二个 应用 Graphics 对象的转换。 如果设置容器和 Graphics 对象的剪裁区域,则从容器内部绘制的项将由两个剪切区域的交集进行剪裁。

嵌套容器中的质量设置

嵌套容器中 ( SmoothingModeTextRenderingHint 等) 的质量设置不是累积的;相反,容器的质量设置暂时取代 Graphics 对象的质量设置。 新建容器时,该容器的质量设置将设置为默认值。 例如,假设你有一个平滑模式为 SmoothingModeAntiAliasGraphics 对象。 创建容器时,容器内的平滑模式是默认的平滑模式。 你可以自由设置容器的平滑模式,从容器内绘制的任何项都将根据你设置的模式进行绘制。 调用 Graphics::EndContainer 后绘制的项目将根据在调用 Graphics::BeginContainer 之前就已就位的平滑模式 (SmoothingModeAntiAlias) 绘制。

嵌套容器的几个层

不限于 Graphics 对象中的一个容器。 可以创建一系列容器,每个容器都嵌套在前面的容器中,还可以指定每个嵌套容器的世界转换、剪切区域和质量设置。 如果从最内层的容器内部调用绘图方法,则将按顺序应用转换,从最内层的容器开始,到最外层的容器结束。 从最内层的容器中绘制的项将以所有剪切区域的交集进行剪切。

以下示例创建 Graphics 对象,并将其文本呈现提示设置为 TextRenderingHintAntiAlias。 该代码创建两个容器,一个容器嵌套在另一个容器中。 外部容器的文本呈现提示设置为 TextRenderingHintSingleBitPerPixel,内部容器的文本呈现提示设置为 TextRenderingHintAntiAlias。 该代码绘制三个字符串:一个来自内部容器,一个来自外部容器,一个来自 Graphics 对象本身。

Graphics graphics(hdc);
GraphicsContainer innerContainer;
GraphicsContainer outerContainer;
SolidBrush brush(Color(255, 0, 0, 255));
FontFamily fontFamily(L"Times New Roman");
Font font(&fontFamily, 36, FontStyleRegular, UnitPixel);

graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

outerContainer = graphics.BeginContainer();

   graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);

   innerContainer = graphics.BeginContainer();
      graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
      graphics.DrawString(L"Inner Container", 15, &font,
         PointF(20, 10), &brush);
   graphics.EndContainer(innerContainer);

   graphics.DrawString(L"Outer Container", 15, &font, PointF(20, 50), &brush);

graphics.EndContainer(outerContainer);

graphics.DrawString(L"Graphics Object", 15, &font, PointF(20, 90), &brush);

下图显示了这三个字符串。 从内部容器和 Graphics 对象绘制的字符串通过抗锯齿进行平滑处理。 由于 TextRenderingHintSingleBitPerPixel 设置,从外部容器绘制的字符串未通过抗锯齿平滑。

有时包含同一字符串的矩形的插图;只有第一行和最后一行中的字符是平滑的