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


Вложенные графические контейнеры

Windows GDI+ предоставляет контейнеры, которые можно использовать для временной замены или расширения части состояния в графическом объекте. Контейнер создается путем вызова метода Graphics::BeginContainer объекта Graphics . Вы можете вызывать Graphics::BeginContainer несколько раз, чтобы сформировать вложенные контейнеры.

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

В следующем примере создается объект Graphics и контейнер в этом объекте Graphics . Преобразование мира объекта Graphics представляет собой преобразование 100 единиц в направлении x и 80 единиц в направлении y. Преобразование мировых координат для контейнера — поворот на 30 градусов. Код выполняет вызов

DrawRectangle(&pen, -60, -30, 120, 60)

Дважды. Первый вызов Graphics::D rawRectangle выполняется внутри контейнера; то есть вызов находится между вызовами Graphics::BeginContainer и Graphics::EndContainer. Второй вызов Graphics::D rawRectangle выполняется после вызова Graphics::EndContainer.

Graphics           graphics(hdc);
Pen                pen(Color(255, 255, 0, 0));
GraphicsContainer  graphicsContainer;

graphics.TranslateTransform(100.0f, 80.0f);

graphicsContainer = graphics.BeginContainer();
   graphics.RotateTransform(30.0f);
   graphics.DrawRectangle(&pen, -60, -30, 120, 60);
graphics.EndContainer(graphicsContainer);

graphics.DrawRectangle(&pen, -60, -30, 120, 60);

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

Снимок экрана: окно с двумя красными прямоугольниками по центру одной и той же точки, но с разными поворотами

 

Отсечение во вложенных контейнерах

В следующем примере показано, как вложенные контейнеры обрабатывают отсеченные области. Код создает объект Graphics и контейнер в этом объекте Graphics . Область обрезки объекта Graphics представляет собой прямоугольник, а область обрезки контейнера — многоточие. Код выполняет два вызова метода Graphics::D rawLine . Первый вызов Graphics::D rawLine находится внутри контейнера, а второй вызов Graphics::D rawLine находится за пределами контейнера (после вызова Graphics::EndContainer). Первая линия отсекается по пересечению двух отсеченных областей. Вторая строка обрезается только прямоугольной областью обрезки объекта Graphics .

Graphics           graphics(hdc);
GraphicsContainer  graphicsContainer;
Pen                redPen(Color(255, 255, 0, 0), 2);
Pen                bluePen(Color(255, 0, 0, 255), 2);
SolidBrush         aquaBrush(Color(255, 180, 255, 255));
SolidBrush         greenBrush(Color(255, 150, 250, 130));

graphics.SetClip(Rect(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;
   path.AddEllipse(75, 50, 100, 150);

  // Construct a region based on the path.
   Region region(&path);
   graphics.FillRegion(&greenBrush, &region);

   graphics.SetClip(&region);
   graphics.DrawLine(&redPen, 50, 0, 350, 300);
graphics.EndContainer(graphicsContainer);

graphics.DrawLine(&bluePen, 70, 0, 370, 300);

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

иллюстрация многоточия внутри прямоугольника, с одной линией, обрезанной эллипсом, а другая — прямоугольником

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

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

Параметры качества ( SmoothingMode, TextRenderingHint и тому подобное) во вложенных контейнерах не являются накопительными; вместо этого параметры качества контейнера временно заменяют параметры качества графического объекта. При создании нового контейнера его параметры качества устанавливаются в значения по умолчанию. Например, предположим, что у вас есть графический объект с режимом сглаживания SmoothingModeAntiAlias. При создании контейнера он имеет режим сглаживания по умолчанию. Вы можете свободно задать режим сглаживания для контейнера, так что все элементы в нем будут рисоваться в соответствии с этим режимом. Элементы, нарисованные после вызова Graphics::EndContainer , будут отрисовыты в режиме сглаживания (SmoothingModeAntiAlias), который был на месте до вызова Graphics::BeginContainer.

Несколько уровней вложенных контейнеров

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

В следующем примере создается объект Graphics и для указания отрисовки текста задано значение TextRenderingHintAntiAlias. Код создает два контейнера, один из которых вложен в другой. Подсказка отрисовки текста внешнего контейнера имеет значение TextRenderingHintSingleBitPerPixel, а подсказка отрисовки текста внутреннего контейнера — TextRenderingHintAntiAlias. Код рисует три строки: одну из внутреннего контейнера, одну из внешнего контейнера и одну из самого объекта Graphics .

Graphics graphics(hdc);
GraphicsContainer innerContainer;
GraphicsContainer outerContainer;
SolidBrush brush(Color(255, 0, 0, 255));
FontFamily fontFamily(L"Times New Roman");
Font font(&fontFamily, 36, FontStyleRegular, UnitPixel);

graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);

outerContainer = graphics.BeginContainer();

   graphics.SetTextRenderingHint(TextRenderingHintSingleBitPerPixel);

   innerContainer = graphics.BeginContainer();
      graphics.SetTextRenderingHint(TextRenderingHintAntiAlias);
      graphics.DrawString(L"Inner Container", 15, &font,
         PointF(20, 10), &brush);
   graphics.EndContainer(innerContainer);

   graphics.DrawString(L"Outer Container", 15, &font, PointF(20, 50), &brush);

graphics.EndContainer(outerContainer);

graphics.DrawString(L"Graphics Object", 15, &font, PointF(20, 90), &brush);

На рисунке ниже показаны эти три строки. Строки, полученные из внутреннего контейнера и объекта Graphics, сглаживаются путем сглаживания. Строка, нарисованная из внешнего контейнера, не сглаживается путем сглаживания из-за параметра TextRenderingHintSingleBitPerPixel.

иллюстрация прямоугольника, содержащего одну и ту же строку; Только символы в первой и последней строках являются гладкими