嵌套图形容器
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::BeginContainer 和 Graphics::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, ®ion);
graphics.SetClip(®ion);
graphics.DrawLine(&redPen, 50, 0, 350, 300);
graphics.EndContainer(graphicsContainer);
graphics.DrawLine(&bluePen, 70, 0, 370, 300);
下图显示了两条剪裁线。
如前面的两个示例所示,转换和剪辑区域在嵌套容器中累积。 如果设置容器的世界转换和 Graphics 对象,这两个转换将应用于从容器内部绘制的项。 首先应用容器的转换,图形 对象的转换将应用第二个。 如果设置容器的剪辑区域和 图形 对象,则从容器内绘制的项将由两个剪辑区域的交集剪裁。
嵌套容器中的质量设置
嵌套容器中的质量设置(SmoothingMode、TextRenderingHint等)不是累积的;相反,容器的质量设置会暂时替换 图形 对象的质量设置。 创建新容器时,该容器的质量设置将设置为默认值。 例如,假设你有一个 图形 对象,其平滑模式为 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 设置,从外部容器中绘制的字符串不会平滑。