Share via


入れ子になっているグラフィックス コンテナーの使用

GDI+ には、Graphics オブジェクト内の状態の一部を一時的に置き換えるまたは拡張するために使用できるコンテナーが用意されています。 コンテナーを作成するには、Graphics オブジェクトの BeginContainer メソッドを呼び出します。 BeginContainer を繰り返し呼び出して、入れ子になったコンテナーを形成できます。 BeginContainer への各呼び出しは、EndContainer への呼び出しとペアにする必要があります。

入れ子になったコンテナーの変換

次の例では、Graphics オブジェクトとその Graphics オブジェクト内にコンテナーを作成します。 Graphics オブジェクトのワールド変換は、x 方向に 100 単位と y 方向に 80 単位への移動です。 コンテナーのワールド変換は 30 度の回転です。 このコードによって、DrawRectangle(pen, -60, -30, 120, 60) の呼び出しが 2 回行われます。 DrawRectangle への最初の呼び出しは、コンテナー内で行われます。つまり、BeginContainerEndContainer のへ呼び出しの間に呼び出されます。 DrawRectangle への2回目の呼び出しは、EndContainer への呼び出しの後に行われます。

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);
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)

前述のコードでは、コンテナーの中から描画された四角形は、まず、コンテナーのワールド変換 (回転) によって変換され、その後、Graphics オブジェクトのワールド変換 (移動) によって変換されます。 コンテナーの外から描画された四角形は、Graphics オブジェクトのワールド変換 (移動) によってのみ変換されます。 次の図は、2 つの四角形を示しています。

Illustration that shows nested containers.

入れ子になったコンテナーのクリッピング

次の例は、入れ子になったコンテナーによるクリッピング領域の処理方法を示しています。 コードでは、Graphics オブジェクトとその Graphics オブジェクト内にコンテナーを作成します。 Graphics オブジェクトのクリッピング領域は四角形であり、コンテナーのクリッピング領域は楕円です。 コードによって、DrawLine メソッドへの呼び出しが 2 回行われます。 DrawLine への最初の呼び出しはコンテナーの中で行われ、DrawLine への2回目の呼び出しはコンテナーの外で (EndContainer への呼び出しの後に) 行われます。 最初の線は、2 つのクリッピング領域の交差部分によってクリッピングされます。 2 番目の線は、Graphics オブジェクトの四角形のクリッピング領域によってのみクリッピングされます。

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);
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)

次の図は、2 つのクリッピングされた線を示しています。

Illustration that shows a nested container with clipped lines.

前述の 2 つの例で示すように、入れ子になったコンテナーでは、変換とクリッピング領域が累積します。 コンテナーと Graphics オブジェクトのワールド変換を設定した場合、両方の変換がコンテナーの中から描画された項目に適用されます。 コンテナーの変換が最初に適用され、Graphics オブジェクトの変換が 2 番目に適用されます。 コンテナーと Graphics オブジェクトのクリッピング領域を設定した場合、コンテナーの中から描画された項目は、2 つのクリッピング領域の交差部分によってクリッピングされます。

入れ子になったコンテナーの品質設定

入れ子になったコンテナーの品質設定 (SmoothingModeTextRenderingHint など) は、累積されません。代わりに、コンテナーの品質設定によって Graphics オブジェクトの品質設定が一時的に置き換えられます。 新しいコンテナーを作成すると、そのコンテナーの品質設定が既定値に設定されます。 たとえば、スムージング モードが AntiAliasGraphics オブジェクトがあるとします。 コンテナーを作成すると、コンテナーの中のスムージング モードが既定のスムージング モードになります。 コンテナーのスムージング モードは自由に設定できます。また、コンテナーの中から描画された項目は、設定したモードに従って描画されます。 EndContainer への呼び出しの後に描画される項目は、BeginContainer への呼び出しの前に配置されていたスムージング モード (AntiAlias) に従って描画されます。

入れ子になったコンテナーの複数のレイヤー

Graphics オブジェクト内のコンテナーは 1 つであるとは限りません。 先行するコンテナーと入れ子になった一連のコンテナーを作成できます。また、それらの入れ子になった各コンテナーに対して、ワールド変換、クリッピング領域、品質設定を指定できます。 最も内側にあるコンテナーの中から描画メソッドを呼び出した場合、最も内側のコンテナーから始まり、最も外側のコンテナーで終わる順番に、変換が適用されます。 最も内側のコンテナーの中から描画された項目は、すべてのクリッピング領域の交差部分によってクリッピングされます。

次の例では、Graphics オブジェクトを作成し、そのテキスト レンダリング ヒントを AntiAlias に設定します。 このコードによって、一方が他方の中に入れ子になった、2 つのコンテナーが作成されます。 外側のコンテナーのテキスト レンダリング ヒントは SingleBitPerPixel に設定され、内側のコンテナーのテキスト レンダリング ヒントは AntiAlias に設定されます。 このコードによって、1 つは内側のコンテナーから、1 つは外側のコンテナーから、1 つは Graphics オブジェクト自体から、3 つの文字列が描画されます。

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 = System.Drawing.Text.TextRenderingHint.AntiAlias;

outerContainer = graphics.BeginContainer();

graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixel;

innerContainer = graphics.BeginContainer();
graphics.TextRenderingHint = System.Drawing.Text.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));
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 = _
System.Drawing.Text.TextRenderingHint.AntiAlias

outerContainer = graphics.BeginContainer()

graphics.TextRenderingHint = _
    System.Drawing.Text.TextRenderingHint.SingleBitPerPixel

innerContainer = graphics.BeginContainer()
graphics.TextRenderingHint = _
    System.Drawing.Text.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))

次の図は、3 つの文字列を示しています。 内側のコンテナーおよび Graphics オブジェクトから描画された文字列は、アンチエイリアシングによってスムージングされます。 外側のコンテナーから描画された文字列は、TextRenderingHint プロパティが SingleBitPerPixel に設定されているため、アンチエイリアシングによってスムージングされません。

Illustration that shows the strings drawn from nested containers.

関連項目