Utilizzo di contenitori di grafica annidati

GDI+ fornisce contenitori che è possibile usare per sostituire o aumentare temporaneamente parte dello stato in un Graphics oggetto . Per creare un contenitore, chiamare il BeginContainer metodo di un Graphics oggetto . È possibile chiamare BeginContainer ripetutamente per formare contenitori annidati. Ogni chiamata a BeginContainer deve essere associata a una chiamata a EndContainer.

Trasformazioni in contenitori annidati

Nell'esempio seguente viene creato un Graphics oggetto e un contenitore all'interno di tale Graphics oggetto. La trasformazione globale dell'oggetto Graphics è una traslazione di 100 unità nella direzione x e 80 unità nella direzione y. La trasformazione globale del contenitore è una rotazione a 30 gradi. Il codice effettua la chiamata DrawRectangle(pen, -60, -30, 120, 60) due volte. La prima chiamata a DrawRectangle è all'interno del contenitore, ovvero la chiamata è tra le chiamate a BeginContainer e EndContainer. La seconda chiamata a DrawRectangle è dopo la chiamata a 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)

Nel codice precedente, il rettangolo disegnato dall'interno del contenitore viene trasformato prima dalla trasformazione globale del contenitore (rotazione) e quindi dalla trasformazione globale dell'oggetto Graphics (conversione). Il rettangolo disegnato dall'esterno del contenitore viene trasformato solo dalla trasformazione globale dell'oggetto Graphics (traduzione). La figura seguente mostra i due rettangoli:

Illustration that shows nested containers.

Ritaglio in contenitori annidati

Nell'esempio seguente viene illustrato come i contenitori annidati gestiscono le aree di ritaglio. Il codice crea un Graphics oggetto e un contenitore all'interno di tale Graphics oggetto. L'area di ritaglio dell'oggetto Graphics è un rettangolo e l'area di ritaglio del contenitore è un'ellisse. Il codice effettua due chiamate al DrawLine metodo . La prima chiamata a DrawLine è all'interno del contenitore e la seconda chiamata a DrawLine si trova all'esterno del contenitore (dopo la chiamata a EndContainer). La prima riga viene ritagliata dall'intersezione delle due aree di ritaglio. La seconda riga viene ritagliata solo dall'area di ritaglio rettangolare dell'oggetto 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)

La figura seguente mostra le due linee ritagliate:

Illustration that shows a nested container with clipped lines.

Come mostrano i due esempi precedenti, le trasformazioni e le aree di ritaglio sono cumulative in contenitori annidati. Se si impostano le trasformazioni del contenitore e dell'oggetto Graphics , entrambe le trasformazioni verranno applicate agli elementi disegnati dall'interno del contenitore. La trasformazione del contenitore verrà applicata per prima e la trasformazione dell'oggetto verrà applicata seconda Graphics . Se si impostano le aree di ritaglio del contenitore e dell'oggetto Graphics , gli elementi disegnati dall'interno del contenitore verranno ritagliati dall'intersezione delle due aree di ritaglio.

Impostazioni di qualità nei contenitori annidati

Le impostazioni di qualità (SmoothingMode, TextRenderingHinte simili) nei contenitori annidati non sono cumulative. Le impostazioni di qualità del contenitore sostituiscono temporaneamente le impostazioni di qualità di un Graphics oggetto. Quando si crea un nuovo contenitore, le impostazioni di qualità per tale contenitore vengono impostate sui valori predefiniti. Si supponga, ad esempio, di avere un Graphics oggetto con una modalità smoothing di AntiAlias. Quando si crea un contenitore, la modalità di smoothing all'interno del contenitore è la modalità di smoothing predefinita. È possibile impostare la modalità di smoothing del contenitore e tutti gli elementi disegnati dall'interno del contenitore verranno disegnati in base alla modalità impostata. Gli elementi disegnati dopo la chiamata a EndContainer verranno disegnati in base alla modalità di smussamento (AntiAlias) terminata prima della chiamata a BeginContainer.

Diversi livelli di contenitori annidati

Non si è limitati a un contenitore in un Graphics oggetto . È possibile creare una sequenza di contenitori, ognuno annidato nel precedente, ed è possibile specificare la trasformazione globale, l'area di ritaglio e le impostazioni di qualità di ognuno di questi contenitori annidati. Se si chiama un metodo di disegno dall'interno del contenitore più interno, le trasformazioni verranno applicate in ordine, a partire dal contenitore più interno e terminando con il contenitore più esterno. Gli elementi disegnati dall'interno del contenitore più interno verranno ritagliati dall'intersezione di tutte le aree di ritaglio.

Nell'esempio seguente viene creato un Graphics oggetto e viene impostato il relativo hint per il rendering del testo su AntiAlias. Il codice crea due contenitori, uno annidato all'interno dell'altro. L'hint per il rendering del testo del contenitore esterno è impostato su SingleBitPerPixele l'hint per il rendering del testo del contenitore interno è impostato su AntiAlias. Il codice disegna tre stringhe: una dal contenitore interno, una dal contenitore esterno e una dall'oggetto Graphics stesso.

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

La figura seguente mostra le tre stringhe. Le stringhe disegnate dal contenitore interno e dall'oggetto Graphics vengono smussate da antialiasing. La stringa disegnata dal contenitore esterno non viene smussata dall'antialiasing perché la TextRenderingHint proprietà è impostata su SingleBitPerPixel.

Illustration that shows the strings drawn from nested containers.

Vedi anche