Contenitori di oggetti Graphics nidificati

In GDI+ sono disponibili contenitori utilizzabili per sostituire temporaneamente o per migliorare parte dello stato in un oggetto Graphics. Per creare un contenitore chiamare il metodo BeginContainer di un oggetto Graphics. È possibile chiamare BeginContainer più volte per creare contenitori nidificati. Ciascuna chiamata a BeginContainer deve essere accoppiata a una chiamata a EndContainer.

Trasformazioni in contenitori nidificati

Nell'esempio che segue viene creato un oggetto Graphics e un contenitore all'interno di esso. La trasformazione complessiva dell'oggetto Graphics consiste in una traslazione di 100 unità sull'asse x e di 80 sull'asse y. La trasformazione world del contenitore consiste in una rotazione di 30 gradi. Viene effettuata due volte la chiamata DrawRectangle(pen, -60, -30, 120, 60). La prima chiamata a DrawRectangle avviene all'interno del contenitore, ovvero viene effettuata tra la chiamata a BeginContainer e la chiamata a EndContainer. La seconda chiamata a DrawRectangle avviene dopo la chiamata a EndContainer.

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)
[C#]
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);

Nel codice precedente al rettangolo disegnato dall'interno del contenitore viene applicata prima una rotazione tramite la trasformazione world del contenitore, poi una traslazione tramite la trasformazione world dell'oggetto Graphics. Al rettangolo disegnato dall'esterno del contenitore viene applicata una traslazione tramite la trasformazione world dell'oggetto Graphics. Nell'illustrazione che segue vengono mostrati i due rettangoli.

Ridimensionamento di contenitori nidificati

Nell'esempio che segue si illustra la gestione delle aree di ridimensionamento da parte dei contenitori nidificati. Viene creato un oggetto Graphics e un contenitore all'interno di esso. L'area di ridimensionamento dell'oggetto Graphics è un rettangolo, mentre quella del contenitore è un'ellisse. Vengono effettuate due chiamate al metodo DrawLine. La prima chiamata a DrawLine è all'interno del contenitore; la seconda chiamata all'esterno, dopo quella a EndContainer. La prima linea viene tagliata dall'intersezione delle due aree di ridimensionamento. La seconda linea viene tagliata solo dall'area di ridimensionamento rettangolare dell'oggetto Graphics.

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)
[C#]
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);

Nell'illustrazione che segue vengono mostrate le due linee tagliate.

Come nei due esempi precedenti, trasformazioni e aree di ridimensionamento sono cumulative nei contenitori nidificati. Se si impostano le trasformazioni world del contenitore e dell'oggetto Graphics, agli elementi disegnati dall'interno del contenitore verranno applicate entrambe le trasformazioni. La trasformazione del contenitore sarà applicata per prima, quella dell'oggetto Graphics per seconda. Se si impostano le aree di ridimensionamento del contenitore e dell'oggetto Graphics gli elementi disegnati dall'interno del contenitore saranno tagliati dall'intersezione delle due aree di ridimensionamento.

Impostazioni di qualità in contenitori nidificati

Le impostazioni di qualità, quali SmoothingMode e TextRenderingHint, nei contenitori nidificati non sono cumulative ma consentono di sostituire temporaneamente le impostazioni di qualità di un oggetto Graphics. Quando si crea un nuovo contenitore le relative impostazioni di qualità sono impostate sui valori predefiniti. Si supponga ad esempio di avere un oggetto Graphics con modalità di smussatura AntiAlias. Quando si crea un contenitore la modalità di smussatura all'interno del contenitore è quella predefinita. È possibile impostare liberamente la modalità di smussatura del contenitore; qualunque elemento disegnato dall'interno di questo sarà creato in conformità alla modalità impostata. Gli elementi disegnati dopo la chiamata a EndContainer saranno creati in base alla modalità di smussatura AntiAlias impostata prima della chiamata a BeginContainer.

Livelli multipli dei contenitori nidificati

In un oggetto Graphics sono disponibili più contenitori. È possibile creare una sequenza di contenitori, ciascuno nidificato nel precedente, specificando la trasformazione world, l'area di ridimensionamento e le impostazioni di qualità di ciascuno di essi. Se si chiama un metodo di creazione dall'interno del contenitore più interno le trasformazioni saranno applicate in ordine, a partire dal contenitore più interno fino a quello più esterno. Gli elementi disegnati dall'interno del contenitore più interno saranno tagliati dall'intersezione di tutte le aree di ridimensionamento.

Nell'esempio che segue si crea un oggetto Graphics e se ne imposta l'hint di rendering del testo su AntiAlias. Vengono creati due contenitori, uno nidificato dentro l'altro. L'hint di rendering di testo del contenitore esterno è impostato su SingleBitPerPixel, mentre quello del contenitore interno è impostato su AntiAlias. Vengono create tre stringhe: una dal contenitore interno, una da quello esterno e una direttamente dell'oggetto Graphics.

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 = TextRenderingHint.AntiAlias

outerContainer = graphics.BeginContainer()

   graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel

   innerContainer = graphics.BeginContainer()
      graphics.TextRenderingHint = 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))
[C#]
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 = TextRenderingHint.AntiAlias;

outerContainer = graphics.BeginContainer();

   graphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;

   innerContainer = graphics.BeginContainer();
      graphics.TextRenderingHint = 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));

Nell'illustrazione che segue sono mostrate le tre stringhe. Alla stringa creata dal contenitore interno e dall'oggetto Graphics è applicata la smussatura tramite antialias. La stringa creata dal contenitore esterno non è smussata tramite antialias perché la proprietà TextRenderingHint è impostata su SingleBitPerPixel.