Uso di contenitori grafici annidati
GDI+ fornisce contenitori che è possibile usare per sostituire o aumentare temporaneamente parte dello stato in un oggetto Graphics. Per creare un contenitore, chiamare il metodo BeginContainer di un oggetto Graphics. È 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 oggetto Graphics e un contenitore all'interno di tale oggetto Graphics. 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 esegue la chiamata DrawRectangle(pen, -60, -30, 120, 60)
due volte. La prima chiamata a DrawRectangle si trova 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 (traduzione). Il rettangolo disegnato al di fuori del contenitore viene trasformato solo dalla trasformazione globale (translation) dell'oggetto Graphics. La figura seguente mostra i due rettangoli:
Ritaglio in contenitori annidati
Nell'esempio seguente viene illustrato come i contenitori annidati gestiscono le regioni di ritaglio. Il codice crea un oggetto Graphics e un contenitore all'interno di tale oggetto Graphics. L'area di ritaglio dell'oggetto Graphics è un rettangolo e l'area di ritaglio del contenitore è un'ellisse. Il codice effettua due chiamate al metodo DrawLine. La prima chiamata a DrawLine si trova 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 è 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:
Come mostrano i due esempi precedenti, le trasformazioni e le aree di ritaglio sono cumulative in contenitori annidati. Se si impostano le trasformazioni mondiali 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 Graphics verrà applicata seconda. Se si impostano le aree di ritaglio del contenitore e dell'oggetto Graphics, gli elementi disegnati dall'interno del contenitore verranno ritagliati nell'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; piuttosto, le impostazioni di qualità del contenitore sostituiscono temporaneamente le impostazioni di qualità di un oggetto Graphics. 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 oggetto Graphics con una modalità di smoothing di AntiAlias. Quando si crea un contenitore, la modalità di levigatura all'interno del contenitore è quella 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 secondo la modalità di smussamento (AntiAlias) che era attiva prima della chiamata a BeginContainer.
Diversi livelli di contenitori annidati
Non sei limitato a un solo contenitore in un oggetto Graphics. È 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 richiama 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 oggetto Graphics e viene impostata l'indicazione di rendering del testo su AntiAlias. Il codice crea due contenitori, uno annidato all'interno dell'altro. Il suggerimento per il rendering del testo del contenitore esterno è impostato su SingleBitPerPixele il suggerimento 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))
L'illustrazione seguente mostra le tre stringhe. Le linee disegnate dal contenitore interno e dall'oggetto Graphics vengono smussate mediante antialiasing. La stringa disegnata dal contenitore esterno non viene smussata dall'antialiasing perché la proprietà TextRenderingHint è impostata su SingleBitPerPixel.
Vedere anche
.NET Desktop feedback