Partager via


Utilisation de conteneurs graphiques imbriqués

GDI+ fournit des conteneurs que vous pouvez utiliser pour remplacer ou augmenter temporairement une partie de l’état dans un objet Graphics. Vous créez un conteneur en appelant la méthode BeginContainer d’un objet Graphics. Vous pouvez appeler BeginContainer à plusieurs reprises pour former des conteneurs imbriqués. Chaque appel à BeginContainer doit être associé à un appel à EndContainer.

Transformations dans des conteneurs imbriqués

L’exemple suivant crée un objet Graphics et un conteneur dans cet objet Graphics. La transformation mondiale de l’objet Graphics est une traduction de 100 unités dans la direction x et 80 unités dans la direction y. La transformation mondiale du conteneur est une rotation de 30 degrés. Le code effectue l’appel DrawRectangle(pen, -60, -30, 120, 60) deux fois. Le premier appel à DrawRectangle se trouve à l’intérieur du conteneur ; autrement dit, l’appel est entre les appels à BeginContainer et EndContainer. Le deuxième appel à DrawRectangle est après l’appel à 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)

Dans le code précédent, le rectangle dessiné à l’intérieur du conteneur est transformé en premier par la transformation mondiale du conteneur (rotation), puis par la transformation mondiale de l’objet Graphics (traduction). Le rectangle dessiné depuis l’extérieur du conteneur est transformé uniquement par la transformation universelle de l’objet Graphics (translation). L’illustration suivante montre les deux rectangles :

Illustration montrant des conteneurs imbriqués.

Découpage dans des conteneurs imbriqués

L’exemple suivant montre comment les conteneurs imbriqués gèrent les régions de découpage. Le code crée un objet Graphics et un conteneur dans cet objet Graphics. La zone de découpage de l’objet Graphics est un rectangle et la zone de découpage du conteneur est un ellipse. Le code effectue deux appels à la méthode DrawLine. Le premier appel à DrawLine se trouve à l’intérieur du conteneur, et le deuxième appel à DrawLine est en dehors du conteneur (après l’appel à EndContainer). La première ligne est découpée par l’intersection des deux régions de découpage. La deuxième ligne est uniquement découpée par la zone de découpage rectangulaire de l’objet 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)

L’illustration suivante montre les deux lignes clippées :

Illustration montrant un conteneur imbriqué avec des lignes clippées.

Comme le montrent les deux exemples précédents, les transformations et les régions de découpage sont cumulatives dans les conteneurs imbriqués. Si vous définissez les transformations du monde du conteneur et de l’objet Graphics, les deux transformations s’appliquent aux éléments dessinés à partir de l’intérieur du conteneur. La transformation du conteneur sera appliquée en premier, et la transformation de l’objet Graphics sera appliquée en deuxième. Si vous définissez les régions de clipping du conteneur et de l’objet Graphics, les éléments dessinés à l’intérieur du conteneur seront clippés par l’intersection des deux régions de clipping.

Paramètres de qualité dans les conteneurs imbriqués

Les paramètres de qualité (SmoothingMode, TextRenderingHintet les autres) dans les conteneurs imbriqués ne sont pas cumulatifs ; au lieu de cela, les paramètres de qualité du conteneur remplacent temporairement les paramètres de qualité d’un objet Graphics. Lorsque vous créez un conteneur, les paramètres de qualité de ce conteneur sont définis sur les valeurs par défaut. Par exemple, supposons que vous disposez d’un objet Graphics avec un mode de lissage de AntiAlias. Lorsque vous créez un conteneur, le mode de lissage à l’intérieur du conteneur est le mode de lissage par défaut. Vous êtes libre de définir le mode de lissage du conteneur, et tous les éléments dessinés à l’intérieur du conteneur seront dessinés en fonction du mode que vous définissez. Les éléments dessinés après l’appel à EndContainer seront dessinés en fonction du mode de lissage (AntiAlias) qui était en place avant l’appel à BeginContainer.

Plusieurs couches de conteneurs imbriqués

Vous n’êtes pas limité à un conteneur dans un objet Graphics. Vous pouvez créer une séquence de conteneurs, chacun imbriqué dans le précédent, et vous pouvez spécifier la transformation mondiale, la région de découpage et les paramètres de qualité de chacun de ces conteneurs imbriqués. Si vous appelez une méthode de dessin à partir du conteneur le plus interne, les transformations sont appliquées dans l’ordre, en commençant par le conteneur le plus interne et en se terminant par le conteneur le plus externe. Les éléments dessinés à l’intérieur du conteneur le plus interne seront découpés par l’intersection de toutes les régions de découpage.

L’exemple suivant crée un objet Graphics et définit son indicateur de rendu de texte sur AntiAlias. Le code crée deux conteneurs, un imbriqué dans l’autre. L’indicateur de rendu de texte du conteneur externe est défini sur SingleBitPerPixel, et l’indicateur de rendu de texte du conteneur interne est défini sur AntiAlias. Le code dessine trois chaînes : l’une du conteneur interne, l’une du conteneur externe et l’autre de l’objet Graphics lui-même.

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’illustration suivante montre les trois chaînes. Les chaînes de caractères tirées du conteneur interne et de l'objet Graphics sont lissées par antialiasing. La chaîne tirée du conteneur externe n’est pas lissée par anticrénelage, car la propriété TextRenderingHint est définie sur SingleBitPerPixel.

Illustration montrant les chaînes dessinées à partir de conteneurs imbriqués.

Voir aussi