嵌套图形容器

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

嵌套容器中的转换

以下示例创建一个 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::D rawLine 方法进行两次调用。 对 Graphics::D rawLine 的第一次调用位于容器内,第二次调用 Graphics::D rawLine 位于容器外部(调用 Graphics::EndContainer后)。 第一行由两个剪辑区域的交集剪裁。 第二行仅由 图形 对象的矩形剪辑区域剪裁。

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 对象,这两个转换将应用于从容器内部绘制的项。 首先应用容器的转换,图形 对象的转换将应用第二个。 如果设置容器的剪辑区域和 图形 对象,则从容器内绘制的项将由两个剪辑区域的交集剪裁。

嵌套容器中的质量设置

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

嵌套容器的多个层

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

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

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 设置,从外部容器中绘制的字符串不会平滑。

一个包含相同字符串的矩形的插图;仅第一行和最后一行中的字符是平滑的