Windows Forms 컨트롤 렌더링

렌더링은 사용자의 화면에서 시각적 표현을 만드는 프로세스를 말합니다. Windows Forms는 렌더링에 GDI(새 Windows 그래픽 라이브러리)를 사용합니다. GDI에 대한 액세스를 제공하는 관리형 클래스는 System.Drawing 네임스페이스와 해당 하위 네임스페이스에 있습니다.

컨트롤 렌더링에는 다음과 같은 요소가 사용됩니다.

  • 기본 클래스 System.Windows.Forms.Control에서 제공하는 그리기 기능

  • GDI 그래픽 라이브러리의 필수 요소

  • 그리기 영역의 기하 도형

  • 그래픽 리소스 해제 절차

컨트롤에서 제공하는 그리기 기능

기본 클래스 Control은 해당 Paint 이벤트를 통해 그리기 기능을 제공합니다. 컨트롤은 표시를 업데이트해야 할 때마다 Paint 이벤트를 발생시킵니다. .NET Framework의 이벤트에 대한 자세한 내용은 이벤트 처리 및 발생을 참조하세요.

Paint 이벤트의 이벤트 데이터 클래스인 PaintEventArgs는 컨트롤을 그리는 데 필요한 데이터(그래픽 개체 핸들 및 그릴 영역을 나타내는 사각형 개체)를 저장합니다. 이러한 개체는 다음 코드 조각에서 굵게 표시됩니다.

Public Class PaintEventArgs  
   Inherits EventArgs  
   Implements IDisposable  
  
   Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle  
      ...  
   End Property  
  
   Public ReadOnly Property Graphics() As System.Drawing.Graphics  
      ...  
   End Property  
   ' Other properties and methods.  
   ...  
End Class  
public class PaintEventArgs : EventArgs, IDisposable {  
public System.Drawing.Rectangle ClipRectangle {get;}  
public System.Drawing.Graphics Graphics {get;}  
// Other properties and methods.  
...  
}  

Graphics는 이 토픽의 뒷부분에 있는 GDI 부분에 설명된 대로 그리기 기능을 캡슐화하는 관리형 클래스입니다. ClipRectangleRectangle 구조 인스턴스로, 컨트롤이 그릴 수 있는 사용 가능한 영역을 정의합니다. 컨트롤 개발자는 이 토픽의 뒷부분에 있는 기하 도형 부분에 설명된 대로 컨트롤의 ClipRectangle 속성을 사용하여 ClipRectangle을 컴퓨팅할 수 있습니다.

컨트롤은 Control에서 상속받은 OnPaint 메서드를 재정의하여 렌더링 논리를 제공해야 합니다. OnPaint는 전달된 PaintEventArgs 인스턴스의 GraphicsClipRectangle 속성을 통해 그릴 사각형과 그래픽 개체에 액세스합니다.

Protected Overridable Sub OnPaint(pe As PaintEventArgs)  
protected virtual void OnPaint(PaintEventArgs pe);  

기본 Control 클래스의 OnPaint 메서드는 그리기 기능을 구현하지 않고 단순히 Paint 이벤트에 등록된 이벤트 대리자를 호출합니다. OnPaint를 재정의할 때는 일반적으로 등록된 대리자가 Paint 이벤트를 받도록 기본 클래스의 OnPaint 메서드를 호출해야 합니다. 그러나 전체 화면을 그리는 컨트롤은 깜박임이 발생하므로 기본 클래스의 OnPaint를 호출하면 안 됩니다. OnPaint 이벤트를 재정의하는 예제는 방법: 진행률을 보여 주는 Windows Forms 컨트롤 만들기를 참조하세요.

참고

컨트롤에서 직접 OnPaint를 호출하는 대신, Control에서 상속받은 Invalidate 메서드 또는 Invalidate를 호출하는 다른 메서드를 호출합니다. 그러면 Invalidate 메서드가 OnPaint를 호출합니다. Invalidate 메서드가 오버로드되고 Invalidatee에 제공된 인수에 따라 컨트롤이 화면 영역의 일부 또는 전체를 다시 그립니다.

기본 Control 클래스는 그리기에 유용한 다른 메서드인 OnPaintBackground 메서드를 정의합니다.

Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)  
protected virtual void OnPaintBackground(PaintEventArgs pevent);  

OnPaintBackground는 창의 배경(그리고 그 모양)을 그리고 속도가 빠른 반면, OnPaint는 세부 정보를 그리고 개별 그리기 요청이 다시 그려야 하는 모든 영역을 포함하는 하나의 Paint 이벤트로 결합되므로 속도가 더 느릴 수 있습니다. 예를 들어 컨트롤의 그라데이션 색 배경을 그리려는 경우 OnPaintBackground를 호출하는 것이 좋습니다.

OnPaintBackground는 이벤트와 유사하게 명명되고 OnPaint 메서드와 동일한 인수를 사용하는 반면, OnPaintBackground는 진정한 이벤트 메서드가 아닙니다. PaintBackground 이벤트는 없으며, OnPaintBackground는 이벤트 대리자를 호출하지 않습니다. OnPaintBackground 메서드를 재정의할 때는 기본 클래스의 OnPaintBackground 메서드를 호출하기 위한 파생 클래스가 필요하지 않습니다.

GDI+ 기본 사항

Graphics 클래스는 원, 삼각형, 원호, 타원 등의 다양한 도형을 그리는 메서드와 텍스트를 표시하는 메서드를 제공합니다. System.Drawing 네임스페이스 및 하위 네임스페이스에는 도형(원, 사각형, 원호 등), 색, 글꼴, 브러시 등의 그래픽 요소를 캡슐화하는 클래스가 포함되어 있습니다. GDI에 대한 자세한 내용은 관리형 그래픽 클래스 사용을 참조하세요. 또한 GDI의 필수 사항은 방법: 진행률을 보여 주는 Windows Forms 컨트롤 만들기에 설명되어 있습니다.

그리기 영역의 기하 도형

컨트롤의 ClientRectangle 속성은 사용자 화면에서 컨트롤이 사용할 수 있는 사각형 영역을 지정하는 반면, PaintEventArgsClipRectangle 속성은 실제로 그려지는 영역을 지정합니다. (그리기는 PaintEventArgs 인스턴스를 인수로 사용하는 Paint 이벤트 메서드에서 수행됨). 컨트롤 표시의 작은 섹션이 변경된 경우와 같이 컨트롤이 사용 가능한 영역의 일부만 그려야 할 수도 있습니다. 이 경우에는 컨트롤 개발자가 그릴 실제 사각형을 컴퓨팅한 후 Invalidate에 전달해야 합니다. Rectangle 또는 Region을 인수로 사용하는 Invalidate의 오버로드된 버전은 해당 인수를 사용하여 PaintEventArgsClipRectangle 속성을 생성합니다.

다음 코드 조각은 FlashTrackBar 사용자 지정 컨트롤이 그릴 사각형 영역을 계산하는 방법을 보여줍니다. client 변수는 ClipRectangle 속성을 나타냅니다. 전체 예제는 방법: 진행률을 보여 주는 Windows Forms 컨트롤 만들기를 참조하세요.

Rectangle invalid = new Rectangle(
    client.X + min,
    client.Y,
    max - min,
    client.Height);

Invalidate(invalid);
Dim invalid As Rectangle = New Rectangle( _
    client.X + lmin, _
    client.Y, _
    lmax - lmin, _
    client.Height)

Invalidate(invalid)

그래픽 리소스 해제

그래픽 개체는 시스템 리소스를 사용하기 때문에 비용이 많이 듭니다. 해당 개체에는 System.Drawing.Graphics 클래스 인스턴스 및 System.Drawing.Brush, System.Drawing.Pen, 기타 그래픽 클래스 인스턴스가 포함됩니다. 필요할 때만 그래픽 리소스를 만들고 사용을 마치면 바로 해제해야 합니다. IDisposable 인터페이스를 구현하는 형식을 만드는 경우 사용을 마치면 해당 Dispose 메서드를 호출하여 리소스를 해제합니다.

다음 코드 조각은 FlashTrackBar 사용자 지정 컨트롤이 Brush 리소스를 만들고 해제하는 방법을 보여 줍니다. 전체 소스 코드는 방법: 진행률을 보여 주는 Windows Forms 컨트롤 만들기를 참조하세요.

private Brush baseBackground = null;
Private baseBackground As Brush
base.OnPaint(e);
if (baseBackground == null) {
    if (showGradient) {
        baseBackground = new LinearGradientBrush(new Point(0, 0),
                                                 new Point(ClientSize.Width, 0),
                                                 StartColor,
                                                 EndColor);
    }
    else if (BackgroundImage != null) {
        baseBackground = new TextureBrush(BackgroundImage);
    }
    else {
        baseBackground = new SolidBrush(BackColor);
    }
}
MyBase.OnPaint(e)

If (baseBackground Is Nothing) Then

    If (myShowGradient) Then
        baseBackground = New LinearGradientBrush(New Point(0, 0), _
                                                 New Point(ClientSize.Width, 0), _
                                                 StartColor, _
                                                 EndColor)
    ElseIf (BackgroundImage IsNot Nothing) Then
        baseBackground = New TextureBrush(BackgroundImage)
    Else
        baseBackground = New SolidBrush(BackColor)
    End If

End If
protected override void OnResize(EventArgs e) {
    base.OnResize(e);
    if (baseBackground != null) {
        baseBackground.Dispose();
        baseBackground = null;
    }
}
Protected Overrides Sub OnResize(ByVal e As EventArgs)
    MyBase.OnResize(e)
    If (baseBackground IsNot Nothing) Then
        baseBackground.Dispose()
        baseBackground = Nothing
    End If
End Sub

참고 항목