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 Graphics objet. Vous créez un conteneur en appelant la BeginContainer méthode d’un Graphics objet. Vous pouvez appeler BeginContainer à plusieurs reprises pour former des conteneurs imbriqués. Chaque appel à doit BeginContainer être associé à un appel à EndContainer.

Transformations dans des conteneurs imbriqués

L’exemple suivant crée un Graphics objet et un conteneur dans cet Graphics objet. 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 est à DrawRectangle l’intérieur du conteneur ; autrement dit, l’appel se trouve 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é à partir de 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é à partir de l’extérieur du conteneur est transformé uniquement par la transformation mondiale de l’objet Graphics (traduction). L’illustration suivante montre les deux rectangles :

Illustration that shows nested containers.

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 Graphics objet et un conteneur dans cet Graphics objet. La zone de découpage de l’objet Graphics est un rectangle, et la région de découpage du conteneur est une ellipse. Le code effectue deux appels à la DrawLine méthode. Le premier appel à se trouve à DrawLine l’intérieur du conteneur, et le deuxième appel est DrawLine 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 clippée uniquement 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 that shows a nested container with clipped lines.

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 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 découpage du conteneur et de l’objet Graphics , les éléments dessinés à l’intérieur du conteneur sont coupés par l’intersection des deux régions de découpage.

Paramètres qualité dans les conteneurs imbriqués

Les paramètres de qualité (SmoothingModeet TextRenderingHintles paramètres similaires) 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 Graphics objet. 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 Graphics objet 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 seront EndContainer 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 Graphics objet. 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 à partir de l’intérieur du conteneur le plus interne seront coupés par l’intersection de toutes les régions de découpage.

L’exemple suivant crée un Graphics objet et définit son indicateur AntiAliasde rendu de texte sur . Le code crée deux conteneurs, un imbriqué dans l’autre. L’indicateur de rendu de texte du conteneur externe est défini SingleBitPerPixelsur , 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 tirées du conteneur interne et de l’objet Graphics sont lissées par anticrénelage. La chaîne tirée du conteneur externe n’est pas lissée par anticrénelage, car la TextRenderingHint propriété est définie sur SingleBitPerPixel.

Illustration that shows the strings drawn from nested containers.

Voir aussi