嵌套图形容器
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::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 对象和一个容器。 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, ®ion);
graphics.SetClip(®ion);
graphics.DrawLine(&redPen, 50, 0, 350, 300);
graphics.EndContainer(graphicsContainer);
graphics.DrawLine(&bluePen, 70, 0, 370, 300);
下图显示了两个已剪裁的行。
如前两个示例所示,转换和剪切区域在嵌套容器中累积。 如果设置容器和 Graphics 对象的世界转换,这两种转换将应用于从容器内部绘制的项。 首先应用容器的转换,第二个 应用 Graphics 对象的转换。 如果设置容器和 Graphics 对象的剪裁区域,则从容器内部绘制的项将由两个剪切区域的交集进行剪裁。
嵌套容器中的质量设置
嵌套容器中 ( SmoothingMode、 TextRenderingHint 等) 的质量设置不是累积的;相反,容器的质量设置暂时取代 Graphics 对象的质量设置。 新建容器时,该容器的质量设置将设置为默认值。 例如,假设你有一个平滑模式为 SmoothingModeAntiAlias 的 Graphics 对象。 创建容器时,容器内的平滑模式是默认的平滑模式。 你可以自由设置容器的平滑模式,从容器内绘制的任何项都将根据你设置的模式进行绘制。 调用 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 设置,从外部容器绘制的字符串未通过抗锯齿平滑。