共用方式為


巢狀圖形容器

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)
[C#]
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)
[C#]
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 物件的品質設定。當您建立新的容器時,該容器的品質設定會設定為預設值。例如,假設您有一個平滑化模式為 AntiAliasGraphics 物件。當您建立容器時,容器內部的平滑化模式就是預設的平滑化模式。您可以任意設定容器的平滑化模式,從容器內部繪製的任何項目都將根據您所設定的模式來進行繪製。在 EndContainer 呼叫之後繪製的項目則將根據 BeginContainer 呼叫之前的平滑化模式 (AntiAlias) 來進行繪製。

巢狀容器中的幾個圖層

您並不受限於 Graphics 物件中的一個容器。您可以建立一連串容器,每一個容器都是套疊於前一個容器內,而且可以為每一個巢狀容器指定自然變換、裁剪區域和品質設定。如果您從最內層的容器呼叫繪圖方法,變換將會從最內層的容器依序套用到最外層的容器。從最內層的容器繪製的項目將根據所有製剪區域的交集來進行裁剪。

下列範例會建立 Graphics 物件,並設定它的 AntiAlias 文字呈現提示。程式碼會建立兩個容器,一個套疊於另一個。外部容器的文字呈現提示是設定為 SingleBitPerPixel,內部容器的文字呈現提示則是設定為 AntiAlias。程式碼會繪製三個字串:一個從內部容器、一個從外部容器,另一個從 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 = TextRenderingHint.AntiAlias

outerContainer = graphics.BeginContainer()

   graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel

   innerContainer = graphics.BeginContainer()
      graphics.TextRenderingHint = 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))
[C#]
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 = TextRenderingHint.AntiAlias;

outerContainer = graphics.BeginContainer();

   graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;

   innerContainer = graphics.BeginContainer();
      graphics.TextRenderingHint = 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