Verwenden geschachtelter Grafikcontainer

GDI+ stellt Container bereit, die Sie verwenden können, um einen Teil des Zustands in einem Graphics-Objekt vorübergehend zu ersetzen oder zu erweitern. Sie erstellen einen Container, indem Sie die BeginContainer-Methode eines Graphics-Objekts aufrufen. Sie können BeginContainer wiederholt aufrufen, um geschachtelte Container zu bilden. Jeder BeginContainer-Aufruf muss mit einem EndContainer-Aufruf gekoppelt werden.

Transformationen in geschachtelten Containern

Im folgenden Beispiel werden ein Graphics-Objekt und ein Container innerhalb dieses Graphics-Objekts erstellt. Bei der globalen Transformation des Graphics-Objekts handelt es sich um eine Translation um 100 Einheiten in x-Richtung und 80 Einheiten in y-Richtung. Die globale Transformation des Containers ist eine Drehung um 30 Grad. Im Code wird der DrawRectangle(pen, -60, -30, 120, 60)-Aufruf zweimal ausgeführt. Der erste DrawRectangle-Aufruf befindet sich innerhalb des Containers, also zwischen dem BeginContainer-Aufruf und dem EndContainer-Aufruf. Der zweite DrawRectangle-Aufruf befindet sich nach dem EndContainer-Aufruf.

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)

Im obigen Code wird das Rechteck, das im Rahmen des Containers gezeichnet wird, zuerst durch die globale Transformation des Containers (Drehung) und dann durch die globale Transformation des Graphics-Objekts (Translation) transformiert. Das Rechteck, das von außerhalb des Containers gezeichnet wird, wird nur durch die globale Transformation des Graphics-Objekts (Translation) transformiert. Die folgende Abbildung zeigt die beiden Rechtecke:

Illustration that shows nested containers.

Clipping in geschachtelten Containern

Das folgende Beispiel veranschaulicht die Behandlung von Clippingbereichen durch geschachtelte Container. Im Code werden ein Graphics-Objekt und ein Container innerhalb dieses Graphics-Objekts erstellt. Der Clippingbereich des Graphics-Objekts ist ein Rechteck, und der Clippingbereich des Containers ist eine Ellipse. Im Code wird zweimal die DrawLine-Methode aufgerufen. Der erste DrawLine-Aufruf befindet sich innerhalb des Containers, der zweite DrawLine-Aufruf außerhalb des Containers (nach dem EndContainer-Aufruf). Die erste Linie wird am Schnittpunkt der beiden Clippingbereiche beschnitten. Die zweite Zeile wird nur durch den rechteckigen Clippingbereich des Graphics-Objekts beschnitten.

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)

In der folgenden Abbildung sind die beiden beschnittenen Linien zu sehen:

Illustration that shows a nested container with clipped lines.

Wie in den beiden vorherigen Beispielen zu sehen, sind Transformationen und Clippingbereiche in geschachtelten Containern kumulativ. Wenn Sie die globalen Transformationen des Containers und des Graphics-Objekts festlegen, gelten beide Transformationen für Elemente, die im Rahmen des Containers gezeichnet werden. Die Transformation des Containers wird zuerst angewendet. Danach folgt die Transformation des Graphics-Objekts. Wenn Sie die Clippingbereiche des Containers und des Graphics-Objekts festlegen, werden Elemente, die im Rahmen des Containers gezeichnet werden, am Schnittpunkt der beiden Clippingbereiche beschnitten.

Qualitätseinstellungen in geschachtelten Containern

Qualitätseinstellungen wie SmoothingMode und TextRenderingHint in geschachtelten Containern sind nicht kumulativ. Vielmehr ersetzen die Qualitätseinstellungen des Containers vorübergehend die Qualitätseinstellungen eines Graphics-Objekts. Wenn Sie einen neuen Container erstellen, sind die Qualitätseinstellungen für diesen Container auf Standardwerte festgelegt. Angenommen, Sie haben ein Graphics-Objekt mit dem Glättungsmodus AntiAlias. Wenn Sie einen Container erstellen, ist der Glättungsmodus innerhalb des Containers der Standardglättungsmodus. Sie können den Glättungsmodus des Containers festlegen, sodass für alle Elemente, die im Rahmen des Containers gezeichnet werden, der von Ihnen festgelegten Modus verwendet wird. Elemente, die nach dem EndContainer-Aufruf gezeichnet werden, werden mit dem Glättungsmodus AntiAlias gezeichnet, der vor dem BeginContainer-Aufruf festgelegt war.

Mehrere Ebenen geschachtelter Container

Sie sind nicht auf einen einzelnen Container in einem Graphics-Objekt beschränkt. Sie können eine Reihe von Containern erstellen, die im jeweils vorherigen Container geschachtelt sind, und die globale Transformation, den Clippingbereich und die Qualitätseinstellungen jedes dieser geschachtelten Container angeben. Wenn Sie eine Zeichenmethode aus dem innersten Container aufrufen, werden die Transformationen der Reihe nach angewendet – vom innersten bis zum äußersten Container. Elemente, die im Rahmen des innersten Containers gezeichnet werden, werden am Schnittpunkt aller Clippingbereiche beschnitten.

Im folgenden Beispiel wird ein Graphics-Objekt erstellt und der Textrenderinghinweis auf AntiAlias festgelegt. Durch den Code werden zwei ineinander geschachtelte Container erstellt. Der Textrenderinghinweis des äußeren Containers wird auf SingleBitPerPixel und der Textrenderinghinweis des inneren Containers auf AntiAlias festgelegt. Durch den Code werden drei Zeichenfolgen gezeichnet: eine aus dem inneren Container, eine aus dem äußeren Container und eine aus dem Graphics-Objekt selbst.

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

Die folgende Abbildung zeigt die drei Zeichenfolgen. Die aus dem inneren Container und aus dem Graphics-Objekt gezeichneten Zeichenfolgen werden durch Antialiasing geglättet. Die aus dem äußeren Container gezeichnete Zeichenfolge wird nicht durch Antialiasing geglättet, da die TextRenderingHint-Eigenschaft auf SingleBitPerPixel festgelegt ist.

Illustration that shows the strings drawn from nested containers.

Siehe auch