Поделиться через


Использование вложенных графических контейнеров

Интерфейс GDI+ предоставляет контейнеры, которые можно использовать, чтобы временно заменить или дополнить некоторую составляющую состояния объекта Graphics. Чтобы создать контейнер, можно вызвать метод BeginContainer объекта Graphics. Для создания вложенных контейнеров можно многократно вызывать метод BeginContainer. Каждому вызову метода BeginContainer должен соответствовать вызов метода EndContainer.

Преобразования во вложенных контейнерах

В приведенном ниже примере создаются объект Graphics и контейнер внутри этого объекта Graphics. Объемным преобразованием объекта Graphics является сдвиг на 100 единиц в направлении оси x и на 80 единиц в направлении оси y. Объемным преобразованием контейнера является поворот на 30 градусов. Код осуществляет вызов метода DrawRectangle(pen, -60, -30, 120, 60) дважды. Первый вызов DrawRectangle осуществляется внутри контейнера. Это значит, что он происходит между вызовами BeginContainer и EndContainer. Второй вызов DrawRectangle происходит после вызова 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)

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

В приведенном выше коде к прямоугольнику, рисуемому внутри контейнера, применяется сначала объемное преобразование контейнера (поворот), а затем объемное преобразование объекта Graphics (сдвиг). К прямоугольнику, рисуемому вне контейнера, применяется только объемное преобразование объекта Graphics (сдвиг). Два нарисованных прямоугольника показаны на следующем рисунке.

Вложенные контейнеры

Обрезка во вложенных контейнерах

В приведенном ниже примере демонстрируется, каким образом вложенные контейнеры работают с областями обрезки. В приведенном примере создаются объект Graphics и контейнер внутри этого объекта Graphics. Областью обрезки объекта Graphics является прямоугольник, а областью обрезки контейнера — эллипс. В коде осуществляются два вызова метода DrawLine. Первый вызов DrawLine осуществляется внутри контейнера, а второй вызов DrawLine — вне контейнера (после вызова метода EndContainer). Первая линия обрезается по области, являющейся пересечением двух указанных областей отсечения. Вторая линия обрезается по прямоугольнику, являющемуся областью обрезки объекта 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)

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

Две обрезанные линии показаны на следующем рисунке.

Вложенный контейнер

Как показывается в двух приведенных выше примерах, преобразования и области обрезки во вложенных контейнерах являются кумулятивными. Если объемные преобразования устанавливаются как для контейнера, так и для объекта Graphics, к отображаемым внутри контейнера объектам применяются оба эти преобразования. Сначала применяется преобразование контейнера, а затем осуществляется преобразование объекта Graphics. Если области обрезки устанавливаются как для контейнера, так и для объекта Graphics, областью обрезки для объектов, отображаемых внутри контейнера, является пересечение указанных областей обрезки.

Параметры качества во вложенных контейнерах

Параметры качества (SmoothingMode, TextRenderingHint и т. д.) во вложенных контейнерах не являются кумулятивными; вместо этого параметры качества контейнера временно замещают параметры качества объекта Graphics. При создании нового контейнера в качестве параметров качества для него устанавливаются значения по умолчанию. Например, рассмотрим объект Graphics с режимом сглаживания AntiAlias. Когда создается контейнер, режим сглаживания в нем является режимом сглаживания по умолчанию. Можно свободно устанавливать режим сглаживания контейнера, и любые объекты, отображаемые внутри этого контейнера, будут рисоваться в установленном режиме. Объекты, рисуемые после вызова метода EndContainer, будут рисоваться с режимом сглаживания (AntiAlias), действовавшим до вызова метода BeginContainer.

Различные уровни вложенных контейнеров

Нет ограничения на использование в объекте Graphics только одного контейнера. Можно создать последовательность контейнеров, вложенных друг в друга, и указать объемное преобразование, область обрезки и параметры качества для каждого из этих вложенных контейнеров. Если вызывается какой-либо метод рисования из контейнера наибольшего уровня вложенности, преобразования применяются по порядку, начиная с этого контейнера и оканчивая контейнером наименьшего уровня вложенности. Объекты, отображаемые из контейнера наибольшей степени вложенности, обрезаются по области, являющейся пересечением всех областей обрезки.

В следующем примере создается объект Graphics, для которого устанавливается режим сглаживания текста AntiAlias. В коде создаются два контейнера, один из них вложен в другой. Для режим сглаживания внешнего контейнера устанавливается значение SingleBitPerPixel, а для режима сглаживания внутреннего контейнера — AntiAlias. Код выводит на экран три строки: одну из внутреннего контейнера, одну из внешнего контейнера и одну из самого объекта 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 = _
        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))

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

Три нарисованные строки показаны на следующем рисунке. Строки, выводимые из внутреннего контейнера и из объекта Graphics, размываются с помощью сглаживания. Строка, выводимая из внешнего контейнера, не подвергается сглаживанию, потому что свойство TextRenderingHint в этом случае имеет значение SingleBitPerPixel.

Вложенные контейнеры

См. также

Ссылки

Graphics

Основные понятия

Управление состоянием объекта Graphics