Udostępnij za pośrednictwem


Używanie zagnieżdżonych kontenerów grafiki

GDI+ udostępnia kontenery, których można użyć do tymczasowego zastąpienia lub rozszerzenia części stanu w Graphics obiekcie. Kontener można utworzyć, wywołując BeginContainer metodę Graphics obiektu. Można wielokrotnie wywoływać BeginContainer kontenery zagnieżdżone. Każde wywołanie musi BeginContainer być sparowane z wywołaniem metody EndContainer.

Przekształcenia w zagnieżdżonych kontenerach

Poniższy przykład tworzy Graphics obiekt i kontener w tym Graphics obiekcie. Transformacja świata Graphics obiektu to tłumaczenie 100 jednostek w kierunku x i 80 jednostek w kierunku y. Światowa transformacja kontenera jest rotacją 30 stopni. Kod wykonuje wywołanie DrawRectangle(pen, -60, -30, 120, 60) dwa razy. Pierwsze wywołanie elementu DrawRectangle znajduje się wewnątrz kontenera, czyli wywołanie jest między wywołaniami do BeginContainer i EndContainer. Drugie wywołanie metody DrawRectangle jest po wywołaniu metody 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)

W poprzednim kodzie prostokąt pobrany z wewnątrz kontenera jest przekształcany najpierw przez transformację świata kontenera (rotację), a następnie przez światową transformację Graphics obiektu (tłumaczenie). Prostokąt narysowany spoza kontenera jest przekształcany tylko przez transformację Graphics świata obiektu (tłumaczenie). Poniższa ilustracja przedstawia dwa prostokąty:

Illustration that shows nested containers.

Tworzenie wycinków w zagnieżdżonych kontenerach

W poniższym przykładzie pokazano, jak zagnieżdżone kontenery obsługują regiony wycinków. Kod tworzy Graphics obiekt i kontener w tym Graphics obiekcie. Obszar przycinania Graphics obiektu jest prostokątem, a wycinek kontenera jest wielokropkiem. Kod wykonuje dwa wywołania DrawLine metody . Pierwsze wywołanie metody znajduje się DrawLine wewnątrz kontenera, a drugie wywołanie metody znajduje się DrawLine poza kontenerem (po wywołaniu metody ).EndContainer Pierwszy wiersz jest przycięty przez przecięcie dwóch regionów wycinków. Drugi wiersz jest przycięty tylko przez prostokątny obszar wycinków Graphics obiektu.

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)

Poniższa ilustracja przedstawia dwa obcięte linie:

Illustration that shows a nested container with clipped lines.

Jak pokazano w dwóch poprzednich przykładach, przekształcenia i regiony wycinków są skumulowane w zagnieżdżonych kontenerach. Jeśli ustawisz przekształcenia świata kontenera i Graphics obiektu, oba przekształcenia zostaną zastosowane do elementów pochodzących z wewnątrz kontenera. Najpierw zostanie zastosowana transformacja kontenera, a przekształcenie Graphics obiektu zostanie zastosowane w drugiej kolejności. Jeśli ustawisz regiony wycinków kontenera i Graphics obiektu, elementy pobierane z wewnątrz kontenera zostaną obcięte przez przecięcie dwóch regionów wycinków.

Ustawienia jakości w zagnieżdżonych kontenerach

Ustawienia jakości (SmoothingMode, TextRenderingHinti podobne) w zagnieżdżonych kontenerach nie są skumulowane. Ustawienia jakości kontenera tymczasowo zastępują ustawienia Graphics jakości obiektu. Podczas tworzenia nowego kontenera ustawienia jakości dla tego kontenera są ustawione na wartości domyślne. Załóżmy na przykład, że masz Graphics obiekt z trybem AntiAliaswygładzania . Podczas tworzenia kontenera tryb wygładzania wewnątrz kontenera jest domyślnym trybem wygładzania. Możesz ustawić tryb wygładzania kontenera, a wszystkie elementy pobierane z wewnątrz kontenera będą rysowane zgodnie z ustawionym trybem. Elementy rysowane po wywołaniu EndContainer metody zostaną narysowane zgodnie z trybem wygładzania (AntiAlias), który był w miejscu przed wywołaniem metody BeginContainer.

Kilka warstw zagnieżdżonych kontenerów

Nie ograniczasz się do jednego kontenera Graphics w obiekcie. Możesz utworzyć sekwencję kontenerów, z których każda jest zagnieżdżona w poprzednim kroku, i można określić ustawienia transformacji świata, wycinków i jakości każdego z tych zagnieżdżonych kontenerów. Jeśli wywołasz metodę rysunku z wewnątrz najbardziej wewnętrznego kontenera, przekształcenia zostaną zastosowane w kolejności, począwszy od najbardziej wewnętrznego kontenera i kończąc na najbardziej zewnętrznym kontenerze. Elementy pobierane z wnętrza najbardziej wewnętrznego kontenera zostaną obcięte przez przecięcie wszystkich regionów wycinków.

Poniższy przykład tworzy Graphics obiekt i ustawia jego wskazówkę renderowania tekstu na AntiAliaswartość . Kod tworzy dwa kontenery, jeden zagnieżdżony w drugiej. Wskazówka renderowania tekstu zewnętrznego kontenera jest ustawiona na SingleBitPerPixelwartość , a wskazówka renderowania tekstu wewnętrznego kontenera ma wartość AntiAlias. Kod rysuje trzy ciągi: jeden z kontenera wewnętrznego, jeden z kontenera Graphics zewnętrznego i jeden z samego obiektu.

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

Na poniższej ilustracji przedstawiono trzy ciągi. Ciągi pobierane z kontenera wewnętrznego i z Graphics obiektu są wygładzone przez antyaliasing. Ciąg pobrany z kontenera zewnętrznego nie jest wygładzony przez antyaliasing, ponieważ TextRenderingHint właściwość jest ustawiona na SingleBitPerPixelwartość .

Illustration that shows the strings drawn from nested containers.

Zobacz też