다음을 통해 공유


중첩된 Graphics 컨테이너 사용

GDI+에서는 Graphics 개체에서 상태의 일부를 일시적으로 바꾸거나 보강하는 데 사용할 수 있는 컨테이너를 제공합니다. Graphics 개체의 BeginContainer 메서드를 호출하여 컨테이너를 만듭니다. 반복적으로 BeginContainer를 호출하여 중첩된 컨테이너를 형성할 수 있습니다. BeginContainer에 대한 각 호출은 EndContainer에 대한 호출과 쌍으로 연결되어야 합니다.

중첩 컨테이너의 변환

다음 예제에서는 Graphics 개체와 해당 Graphics 개체 내 컨테이너를 만듭니다. Graphics 개체의 월드 변환은 x 방향으로 100단위를 이동하고 y 방향으로 80단위를 이동합니다. 컨테이너의 월드 변환은 30도 회전입니다. 코드는 DrawRectangle(pen, -60, -30, 120, 60)을 두 번 호출합니다. 첫 번째 DrawRectangle 호출은 컨테이너 내에 있습니다. 즉, 호출이 BeginContainer 호출과 EndContainer 호출 사이에 있습니다. 두 번째 DrawRectangle 호출은 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)

앞의 코드에서 컨테이너 내부에서 가져온 사각형은 먼저 컨테이너의 월드 변환(회전)에 의해 변환된 다음 Graphics 개체의 월드 변환(이동)으로 변환됩니다. 컨테이너 외부에서 가져온 사각형은 Graphics 개체의 월드 변환(이동)에 의해서만 변환됩니다. 다음 그림은 두 개의 사각형을 보여줍니다.

중첩된 컨테이너를 보여주는 그림.

중첩된 컨테이너에서 클리핑

다음 예제에서는 중첩된 컨테이너가 클리핑 영역을 처리하는 방법을 보여줍니다. 코드는 Graphics 개체와 해당 Graphics 개체 내 컨테이너를 만듭니다. Graphics 개체의 클리핑 영역은 사각형이고 컨테이너의 클리핑 영역은 타원입니다. 코드는 DrawLine 메서드를 두 번 호출합니다. 첫 번째 DrawLine 호출은 컨테이너 내에 있고, 두 번째 DrawLine 호출은 컨테이너 밖에 있습니다(EndContainer 호출 다음). 첫 번째 줄은 두 클리핑 영역의 교차에 의해 잘립니다. 두 번째 줄은 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)

다음 그림은 잘린 두 개의 선을 보여줍니다.

잘린 선이 있는 중첩된 컨테이너를 보여주는 그림.

앞의 두 예제에서 보여주듯이, 변환 및 클리핑 영역은 중첩된 컨테이너에서 누적됩니다. 컨테이너와 Graphics 개체의 월드 변환을 설정하는 경우 두 변환 모두 컨테이너 내부에서 가져온 항목에 적용됩니다. 컨테이너의 변환이 먼저 적용되고 Graphics 개체의 변환이 두 번째로 적용됩니다. 컨테이너와 Graphics 개체의 클리핑 영역을 설정하는 경우 컨테이너 내부에서 가져온 항목은 두 클리핑 영역의 교차에 의해 잘립니다.

중첩 컨테이너의 품질 설정

중첩된 컨테이너의 품질 설정(SmoothingMode, TextRenderingHint 등)은 누적되지 않습니다. 오히려, 컨테이너의 품질 설정은 일시적으로 Graphics 개체의 품질 설정을 대체합니다. 새 컨테이너를 만들 때 해당 컨테이너의 품질 설정이 기본값으로 설정됩니다. 예를 들어, AntiAlias의 평활 모드가 있는 Graphics 개체가 있다고 가정합니다. 컨테이너를 만들 때 컨테이너 내의 평활 모드는 기본 평활 모드입니다. 컨테이너의 평활 모드를 자유롭게 설정할 수 있으며, 컨테이너 내부에서 가져온 모든 항목은 설정한 모드에 따라 그려집니다. EndContainer 호출 후 그려진 항목은 BeginContainer 호출 전에 배치된 평활 모드(AntiAlias)에 따라 그려집니다.

중첩된 컨테이너의 여러 레이어

Graphics 개체에서는 하나의 컨테이너로 제한되지 않습니다. 앞에서는 각각 중첩된 컨테이너 시퀀스를 만들 수 있으며, 이러한 중첩된 컨테이너 각각의 월드 변환, 클리핑 영역 및 품질 설정을 지정할 수 있습니다. 맨 안쪽에 있는 컨테이너 내에서 그리기 메서드를 호출하면 가장 안쪽 컨테이너에서 시작해서 가장 바깥쪽 컨테이너로 끝나는 순서대로 변환이 적용됩니다. 가장 안쪽 컨테이너 내부에서 가져온 항목은 모든 클리핑 영역의 교차점에 의해 잘립니다.

다음 예제에서는 Graphics 개체를 만들고 텍스트 렌더링 힌트를 AntiAlias로 설정합니다. 코드는 하나가 다른 컨테이너 내에 중첩된 방식으로, 두 개의 컨테이너를 생성합니다. 바깥쪽 컨테이너의 텍스트 렌더링 힌트는 SingleBitPerPixel로 설정되고, 안쪽 컨테이너의 텍스트 렌더링 힌트는 AntiAlias로 설정됩니다. 코드는 세 개의 문자열을 그립니다. 하나는 안쪽 컨테이너에서, 하나는 바깥쪽 컨테이너에서, 다른 하나는 Graphics 개체 자체에서 그립니다.

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

다음 그림은 세 개의 문자열을 보여줍니다. 안쪽 컨테이너와 Graphics 개체에서 그려진 문자열은 앤티앨리어싱으로 부드럽게 됩니다. TextRenderingHint 속성이 SingleBitPerPixel로 설정되었기 때문에 바깥쪽 컨테이너에서 그려진 문자열은 앤티앨리어싱으로 부드럽게 처리되지 않습니다.

중첩된 컨테이너에서 그려진 문자열을 보여주는 그림.

참고 항목