Freigeben über


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 erstellen. Jeder BeginContainer-Aufruf muss mit einem EndContainer-Aufruf gekoppelt werden.

Transformationen in geschachtelten Containern

Im folgenden Beispiel wird ein Graphics-Objekt und ein Container innerhalb dieses Graphics Objekts erstellt. Bei der globalen Transformation des Graphics-Objekts handelt es sich um eine Verschiebung 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 Aufruf von DrawRectangle befindet sich innerhalb des Containers; das heißt, er erfolgt zwischen den Aufrufen von BeginContainer und EndContainer. 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:

Abbildung: Geschachtelte Container

Clipping in geschachtelten Containern

Das folgende Beispiel veranschaulicht die Behandlung von Clippingbereichen durch geschachtelte Container. Der Code erstellt ein Graphics-Objekt und einen Container innerhalb dieses Graphics Objekts. Der Beschneidungsbereich des Graphics-Objekts ist ein Rechteck, und der Beschneidungsbereich des Containers ist eine Ellipse. Der Code führt zwei Aufrufe der DrawLine-Methode durch. Der erste Aufruf von DrawLine befindet sich innerhalb des Containers, und der zweite Aufruf von DrawLine befindet sich außerhalb des Containers (nach dem Aufruf von EndContainer). 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)

Die folgende Abbildung zeigt die beiden beschnittenen Linien:

Abbildung: Geschachtelter Container mit beschnittenen Linien

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, und die Transformation des Graphics-Objekts wird zweitens angewendet. 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 (SmoothingMode, TextRenderingHintund ähnliches) in geschachtelten Containern sind nicht kumulativ; Stattdessen ersetzen die Qualitätseinstellungen des Containers vorübergehend die Qualitätseinstellungen eines Graphics Objekts. Wenn Sie einen neuen Container erstellen, werden 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 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. Der Code erstellt zwei Container, einer innerhalb des anderen geschachtelt. Der Textrenderinghinweis des äußeren Containers wird auf SingleBitPerPixel und der Textrenderinghinweis des inneren Containers auf AntiAlias festgelegt. Der Code zieht drei Strings: einen aus dem inneren Container, einen aus dem äußeren Container und einen 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.

Abbildung: Aus geschachtelten Containern gezeichnete Zeichenfolgen

Siehe auch