GDI+ には、Graphics オブジェクトの状態の一部を一時的に置換または拡張するために使用できるコンテナーが用意されています。 コンテナーを作成する場合は、BeginContainer オブジェクトの Graphics メソッドを呼び出します。 BeginContainer を繰り返し呼び出して、入れ子になったコンテナーを形成できます。 BeginContainer への各呼び出しは、EndContainerの呼び出しとペアにする必要があります。
入れ子式コンテナの変換
次の例では、Graphics オブジェクトとその Graphics オブジェクト内にコンテナーを作成します。
Graphics オブジェクトのワールド変換は、x 方向に 100 単位と y 方向に 80 単位への移動です。 コンテナーのワールド変換は 30 度の回転です。 このコードは DrawRectangle(pen, -60, -30, 120, 60)
を2回呼び出します。
DrawRectangle の最初の呼び出しはコンテナー内にあります。つまり、呼び出しは、BeginContainer と EndContainerへの呼び出しの間にあります。
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 つの四角形を示しています。
入れ子になったコンテナーのクリッピング
次の例は、入れ子になったコンテナーがクリッピング領域を処理する方法を示しています。 このコードにより、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 つのクリップされた行を示しています。
前の 2 つの例に示すように、入れ子になったコンテナーでは変換とクリッピング領域が累積されます。 コンテナーと Graphics オブジェクトのワールド変換を設定すると、両方の変換がコンテナー内から描画された項目に適用されます。 コンテナーの変換が最初に適用され、Graphics オブジェクトの変換が 2 番目に適用されます。 コンテナーと Graphics オブジェクトのクリッピング領域を設定すると、コンテナー内から描画された項目は、2 つのクリッピング領域の交差部分によってクリップされます。
入れ子になったコンテナーの品質設定
入れ子になったコンテナーの品質設定 (SmoothingMode、TextRenderingHintなど) は累積されません。代わりに、コンテナーの品質設定によって、Graphics オブジェクトの品質設定が一時的に置き換えられます。 新しいコンテナーを作成すると、そのコンテナーの品質設定が既定値に設定されます。 たとえば、スムージング モードが Graphicsの AntiAlias オブジェクトがあるとします。 コンテナーを作成する場合、コンテナー内のスムージング モードが既定のスムージング モードになります。 コンテナーのスムージング モードは自由に設定でき、コンテナー内から描画されるすべての項目は、設定したモードに従って描画されます。 EndContainer の呼び出しの後に描画された項目は、AntiAliasへの呼び出しの前に配置されていたスムージング モード (BeginContainer) に従って描画されます。
入れ子になったコンテナーの複数のレイヤー
Graphics オブジェクト内のコンテナーは 1 つに限定されません。 前の手順で入れ子になったコンテナーのシーケンスを作成できます。また、入れ子になった各コンテナーのワールド変換、クリッピング領域、品質設定を指定できます。 最も内側のコンテナー内から描画メソッドを呼び出すと、最も内側のコンテナーから始まり、最も外側のコンテナーで終わる順に変換が適用されます。 最も内側のコンテナーの中から描画された項目は、すべてのクリッピング領域の交差部分によってクリッピングされます。
次の例では、Graphics オブジェクトを作成し、そのテキスト レンダリング ヒントを AntiAliasに設定します。 このコードでは、2つのコンテナーが作成されます。1つは他のコンテナー内に内包されます。 外側のコンテナーのテキストレンダリングヒントは SingleBitPerPixelに設定され、内部コンテナーのテキストレンダリングヒントは AntiAliasに設定されます。 このコードでは、内部コンテナーから 1 つ、外側のコンテナーから 1 つ、Graphics オブジェクト自体から 1 つの 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に設定されているため、外側のコンテナーから描画された文字列はアンチエイリアシングによって平滑化されません。
こちらも参照ください
- Graphics
- グラフィックス オブジェクト の状態の管理
.NET Desktop feedback