MSDN : http://msdn2.microsoft.com/en-us/library/ms748373.aspx

WPF Graphics Rendering Overview

이 토픽은 WPF 비주얼 레이어의 개요를 제공하며 WPF 모델에서 렌더링 지원을 위한 Visual 클래스의 역할에 초점을 맞추고 있습니다.

이 토픽은 다음 섹션을 담고 있습니다.
Visual 객체의 역할

Visual 클래스는 모든 FrameworkElement 객체가 파생(derive)하는 기본 추상 클래스입니다. 또한 WPF에서 새 컨트롤을 작성하는 엔트리 포인트와 Win32 애플리케이션 모델에서의 윈도 핸들(HWND)처럼 생각할 수 있는 많은 방법을 제공합니다.

Visual 객체는 핵심 WPF 객체로써 주 역할은 렌더링 지원을 제공하는 것입니다. Button이나 TextBox와 같은 사용자 인터페이스 컨트롤은 Visual 클래스에서 파생되며, 렌더링 데이터를 지속하기 위해 사용합니다. Visual 객체는 다음 지원을 제공합니다.
  • 화면 출력 : 비주얼의 그릴 내용을 지속적으로, 직렬화하여 렌더링.
  • 변형(Transformations) : 비주얼 상의 변형을 실행.
  • 클리핑(Clipping) : 비주얼을 위한 클리핑 영역(region) 지원을 제공.
  • 충돌 검사(Hit testing) : 좌표나 지오메트리가 비주얼의 영역 내에 포함되는지를 결정.
  • 경계 박스(Bounding box) 계산 : 비주얼의 경계 사각형(Bounding rectangle)을 결정.
※역주: Bounding rectangle은 어떤 비정형의 비주얼 객체를 완전히 포함하는 최소의 크기를 가진 사각형을 말합니다. 다음 그림을 참고하십시오.


그러나 Visual 객체는 다음과 같은 비렌더링 기능을 위한 지원은 포함하지 않습니다.
  • 이벤트 핸들링
  • 레이아웃
  • 스타일
  • 데이터 바인딩
  • 세계화(Globalization)
Visual은 파생되어야 하는 자식 클래스로부터 public abstract 클래스로써 노출됩니다. 다음 그림은 WPF에서 노출되는 비주얼 객체의 계층 구조를 보여줍니다.

Visual 클래스 계층 구조
사용자 삽입 이미지

DrawingVisual 클래스
DrawingVisual은 도형, 이미지나 텍스트를 그리는 가벼운 드로잉 클래스입니다. 이 클래스는 레이아웃이나 이벤트 핸들링을 제공하지 않기 때문에 그것의 런타임 성능을 향상시키는 가벼움이 고려되었습니다. 이런 이유로 드로잉은 배경과 클립아트에 이상적입니다. DrawingVisual은 사용자 정의 비주얼 객체를 생성하는데 사용될 수도 있습니다. 더 자세한 정보는 Using DrawingVisual Objects를 참고하십시오.

Viewport3DVisual 클래스
Viewport3DVisual2D VisualVisual3D 객체간의 다리를 제공합니다. Visual3D 클래스는 모든 3D 비주얼 엘리먼트를 위한 기반 클래스입니다. Viewport3DVisualCamera 값과 Viewport 값의 정의를 요구합니다. 카메라(camera)는 씬(scene)을 볼(view) 수 있게 합니다. 뷰포트(viewport)는 2D 표면상에 프로젝션 맵을 생성합니다. WPF에서의 3D에 관한 더 자세한 정보는 3-D Graphics Overview를 참고하십시오.

ContainerVisual 클래스
ContainerVisual 클래스는 Visual 객체의 컬렉션을 위한 컨테이너로써 사용됩니다. DrawingVisual 클래스는 비주얼 객체의 컬렉션을 담을 수 있게 하는 ContainerVisual 클래스에서 파생됩니다.

Visual 객체에서 드로잉 컨텐트
Visual
객체는 자신의 렌더 데이터를 벡터 그래픽 인스트럭션 목록(vector graphics instruction list)으로 저장합니다. 인스트럭션(※역주:단위 명령어) 목록의 각 아이템은 그래픽 데이터와 연관된 리소스의 로우레벨 세트를 직렬화된 포맷으로 나타냅니다. 드로잉 컨텐트를 담을 수 있는 렌더 데이터는 네 가지 종류가 있습니다.

드로잉 컨텐트 종류
설명
벡터 그래픽
벡터 그래픽 데이터 및 모든 연관된 BrushPen 정보를 나타냅니다.
이미지
Rect에 의해 정의된 영역(region) 내의 이미지를 나타냅니다.
도안(Glyph)
특정 폰트 리소스의 도안 순서인 GlyphRun을 그리는 드로잉을 나타냅니다. 텍스트는 이렇게 해서 표시됩니다.
비디오
비디오를 그리는 드로잉을 나타냅니다.


DrawingContextVisual이 비주얼 컨텐트와 함께 위치할 수 있도록 합니다. DrawingContext 객체의 draw 커맨드를 사용하면 실제로는 그래픽 시스템에 의해 나중에 사용될 렌더 데이터의 세트를 저장하게되며 실시간으로 스크린에 드로잉하는 것이 아닙니다.

Button과 같은 WPF 컨트롤을 만든다면 컨트롤은 명시적으로 스스로를 드로잉할 렌더 데이터를 생성합니다. 예를 들어, ButtonContent 속성을 설정함으로써 컨트롤이 도안의 렌더링 표현을 저장하게 합니다.

VisualDrawingGroup내에 담긴 하나 이상의 Drawing 객체로 그것의 컨텐트를 설명합니다. DrawingGroup은 또한 불투명도 마스크, 변형, 비트맵 효과 및 컨텐트에 적용될 다른 오퍼레이션을 설명합니다. DrawingGroup 명령은 컨텐트가 그려질 때 다음 순서로 적용됩니다. OpacityMask, Opacity, BitmapEffect, ClipGeometry, GuidelineSet 그리고 Transform.

다음 그림은 렌더링 시퀀스동안 적용되는 DrawingGroup 오퍼레이션의 순서를 보여줍니다.

DrawingGroup 오퍼레이션의 순서
사용자 삽입 이미지
더 자세한 정보는 Drawing Objects Overview를 참고하십시오.

Visual 레이어에서의 드로잉 컨텐트
DrawingContext
를 직접 인스턴스화 할 수 없으며, System.Windows.Media.DrawingGroup.Open이나 System.Windows.Media.DrawingVisual.RenderOpen과 같은 메소드를 통해 드로잉 컨텍스트를 획득할 수 있습니다. 다음 예제는 DrawingVisual에서 DrawingContext를 얻고 사각형을 그리는데 사용합니다.

C#
// 사각형을 포함한 DrawingVisual을 생성.
private DrawingVisual CreateDrawingVisualRectangle()
{
    DrawingVisual drawingVisual = new DrawingVisual();

    // 새 드로잉을 생성하기 위해 DrawingContext얻음.
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    // 사각형을 생성하고 DrawingContext로 그것을 칠함.
    Rect rect = new Rect(new Point(160, 100), new Size(320, 80));
    drawingContext.DrawRectangle(Brushes.LightBlue, (Pen)null, rect);

    // 드로잉 컨텐트를 지속.
    drawingContext.Close();

    return drawingVisual;
}

비주얼 레이어에 있는 드로잉 컨텐트 열거
추가적인 다른 사용법으로, Drawing 객체는 또한 Visual의 켄텐츠를 열거하기 위한 객체 모델을 제공합니다.

노트:
비주얼의 컨텐츠를 열거하면 Drawing 객체를 얻을 수 있지만 근본적으로 벡터 그래픽 인스트럭션 리스트로써 렌더 데이터의 표현을 얻을 수 없습니다.

다음 예제는 GetDrawing 메소드를 사용하여 VisualDrawingGroup 값을 얻고 열거합니다.

C#
public void RetrieveDrawing(Visual v)
{
    DrawingGroup dGroup = VisualTreeHelper.GetDrawing(v);
    EnumDrawingGroup(dGroup);

}

// DrawingGroup내의 드로잉을 열거.
public void EnumDrawingGroup(DrawingGroup drawingGroup)
{
     DrawingCollection dc = drawingGroup.Children;

     // 드로잉 컬렉션에 있는 드로잉을 열거.
     foreach (Drawing drawing in dc)
     {
         // 드로잉이 DrawingGroup이면, 재귀 호출.
         if (drawing.GetType() == typeof(DrawingGroup))
         {
             EnumDrawingGroup((DrawingGroup)drawing);
         }
         else if (drawing.GetType() == typeof(GeometryDrawing))
         {
             // 드로잉 종류에 따른 동작 실행.
         }
         else if (drawing.GetType() == typeof(ImageDrawing))
         {
             // 드로잉 종류에 따른 동작 실행.
         }
         else if (drawing.GetType() == typeof(GlyphRunDrawing))
         {
             // 드로잉 종류에 따른 동작 실행.
         }
         else if (drawing.GetType() == typeof(VideoDrawing))
         {
             // 드로잉 종류에 따른 동작 실행.
         }
     }
}

비주얼 객체가 컨트롤을 빌드하는 방법

많은 WPF의 객체는 다른 비주얼 객체들로 구성되어 있으며 변화하는 자손 객체의 계층구조를 담을 수 있다는 걸 의미합니다. WPF의 컨트롤과 같은 많은 사용자 인터페이스 엘리먼트는 렌더링 엘리먼트의 다른 종류를 나타내는 다중 비주얼 객체로 구성되어 있습니다. 예를 들어 Button 컨트롤은 ClassicBorderDecorator, ContentPresenterTextBlock을 포함한 여러개의 다른 객체를 담을 수 있습니다.

다음 코드는 마크업에서 정의된 Button 컨트롤을 보여줍니다.

XAML
<Button Click="OnClick">OK</Button>


기본적인 Button 컨트롤을 구성하는 비주얼 객체를 열거한다면 아래와 같은 비주얼 객체의 계층 구조를 확인할 수 있을 것입니다.

비주얼 트리 계층 구조의 다이어그램

Button 컨트롤은 ContentPresenter 엘리먼트를 포함하는 ClassicBorderDecorator 엘리먼트를 포함합니다. ClassicBorderDecorator 엘리먼트는 Button을 위한 테두리와 배경을 그릴 책임이 있습니다. ContentPresenter 엘리먼트는 Button의 내용을 표시할 책임이 있습니다. 이 경우에서 텍스트를 표시하기 때문에 ContentPresenter 엘리먼트는 TextBlock 엘리먼트를 포함합니다. Button 컨트롤이 ContentPresenter를 사용한다는 사실은 컨텐트가 ImageEllipseGeometry와 같은 다른 엘리먼트로 대체될 수 있다는 것을 의미합니다.

컨트롤 템플릿
컨트롤의 계층으로 컨트롤을 확장하는 핵심은 ControlTemplate입니다. 컨트롤 템플릿은 컨트롤의 기본 비주얼 계층을 말합니다. 명시적으로 컨트롤을 참조하면 암시적으로 그것의 비주얼 계층을 참조합니다. 컨트롤을 사용자 정의된 비주얼 형태로 만들기 위해 컨트롤 템플릿의 기본 값을 오버라이드 할 수 있습니다. 예를 들어 Button 컨트롤의 배경 색상 값을 단일 색상 값 대신 선형 그레이디언트 색상 값으로 변경할 수 있습니다. 더 자세한 정보는 Button ControlTemplate Example을 참고하십시오.

Button 컨트롤과 같은 사용자 인터페이스 엘리먼트는 컨트롤의 전체 렌더링 정의를 설명하는 몇 개의 벡터 그래픽 인스트럭션 리스트를 포함합니다. 다음 코드는 마크업에서 정의된 Button 컨트롤을 보여줍니다.

XAML
<Button Click="OnClick">
  <Image Source="images\greenlight.jpg"></Image>
</Button>

Button 컨트롤을 구성하는 비주얼 객체와 벡터 그래픽 인스트럭션 리스트를 열거한다면 아래 그림과 같은 객체의 계층 구조를 확인할 수 있을 것입니다.

비주얼 트리와 렌더링 데이터의 다이어그램

Button 컨트롤은 ContentPresenter 엘리먼트를 포함하는 ClassicBorderDecorator 엘리먼트를 포함합니다. ClassicBorderDecorator 엘리먼트는 버튼의 경계나 배경을 만드는 모든 구분된 그래픽 엘리먼트를 그릴 책임을 가지고 있습니다. ContentPresenter 엘리먼트는 Button의 내용을 표시할 책임이 있습니다. 이 경우에서 이미지를 표시하기 때문에 ContentPresenter 엘리먼트는 Image 엘리먼트를 포함하게 됩니다.

비주얼 객체와 벡터 그래픽 인스트럭션 목록에 관하여 주의해야 할 몇 가지 사항이 있습니다.
  • 계층 구조에서 순서는 드로잉 정보의 렌더링 순서를 말합니다. 루트 비주얼 엘리먼트에서 자식 엘리먼트까지 왼쪽에서 오른쪽, 위에서 아래로 순회(traversed)됩니다. 엘리먼트가 비주얼 차일드 엘리먼트를 가진다면 엘리먼트의 형제보다 먼저 순회됩니다.
  • 계층 구조에서 ContentPresenter와 같은 리프가 아닌 노드 엘리먼트는 자식 엘리먼트를 담게 되며 인스트럭션 목록을 포함하지 않습니다.
  • 비주얼 엘리먼트가 벡터 그래픽 인스트럭션 리스트와 비주얼 자식 모두를 포함한다면 부모 비주얼 엘리먼트에 있는 인스트럭션 목록은 어떤 자식 비주얼 객체에 있는 드로잉보다 먼저 그려집니다.
  • 벡터 그래픽 인스트럭션 목록에 있는 아이템은 왼쪽에서 오른쪽으로 그려집니다.
비주얼 트리

비주얼 트리는 애플리케이션의 사용자 인터페이스에 사용되는 모든 비주얼 엘리먼트를 포함합니다. 비주얼 엘리먼트가 지속되는 드로잉 정보를 담기 때문에 비주얼 트리를 디스플레이 장치에 출력물을 구성하기 위해 필요한 모든 렌더링 정보를 담는 씬 그래프로 생각할 수 있습니다. 이 트리는 코드든 마크업이든 애플리케이션에 의해 직접적으로 생성된 모든 비주얼 엘리먼트의 집합입니다. 비주얼 트리는 또한 컨트롤과 데이터 객체와 같은 엘리먼트의 템플릿 확장에 의해 생성된 모든 비주얼 엘리먼트도 포함합니다.

다음 코드는 마크업에서 정의된 StackPanel 엘리먼트를 보여줍니다.

XAML
<StackPanel>
  <Label>User name:</Label>
  <TextBox />
  <Button Click="OnClick">OK</Button>
</StackPanel>

마크업 예제의 StackPanel 엘리먼트를 구성하는 비주얼 객체를 열거한다면 아래 그림과 같은 비주얼 객체의 계층 구조를 확인할 수 있을 것입니다.

비주얼 트리 계층 구조의 다이어그램


렌더링 순서
비주얼 트리는 WPF 비주얼과 드로잉 객체의 렌더링 순서를 결정합니다. 순회의 순서는 비주얼 트리의 최상위 노드인 루트 비주얼에서 시작됩니다. 루트 비주얼의 자식은 왼쪽에서 오른쪽으로 순회됩니다. 비주얼이 자식을 가진다면 그 자식은 비주얼의 형제보다 먼저 순회됩니다. 이것은 자식 비주얼의 컨텐트는 비주얼 자신의 컨텐트에 앞서 그려진다는 것을 의미합니다.

비주얼 트리 렌더링 순서의 다이어그램


루트 비주얼
root visual
은 비주얼 트리 계층 구조에서 최상위 엘리먼트입니다. 대부분의 애플리케이션에서 루트 비주얼의 기반 클래스는 Window 또는 NavigateWindow입니다. 그러나 Win32 애플리케이션에서 비주얼 객체를 호스팅한다면 루트 비주얼은 Win32 윈도에서 호스팅한 최상위 비주얼이 될 것입니다. 더 자세한 정보는 Tutorial: Hosting Visual Objects in a Win32 Application을 참고하십시오.

로지컬 트리와의 관계
WPF에서 로지컬 트리는 런타임시 애플리케이션의 엘리먼트를 말합니다. 비록 이 트리를 직접 다루지 않더라도 이 애플리케이션의 뷰는 속성 상속과 이벤트 라우팅을 이해하는데 유용합니다. 비주얼 트리와는 다르게 로지컬 트리는 ListItem과 같은 비-비주얼 데이터 객체를 나타낼 수 있습니다. 많은 경우에서 로지컬 트리는 애플리케이션의 마크업 정의와 매우 밀접하게 연결됩니다. 다음 코드는 마크업에서 정의된 DockPanel 엘리먼트를 보여줍니다.

XAML
<DockPanel>
  <ListBox>
    <ListBoxItem>Dog</ListBoxItem>
    <ListBoxItem>Cat</ListBoxItem>
    <ListBoxItem>Fish</ListBoxItem>
  </ListBox>
  <Button Click="OnClick">OK</Button>
</DockPanel>


마크업 예제의 DockPanel 엘리먼트를 구성하는 로지컬 객체를 열거한다면 아래 그림과 같은 로지컬 객체의 계층 구조를 확인할 수 있을 것입니다.

로지컬 트리의 다이어그램

비주얼 트리와 로지컬 트리 모두 애플리케이션의 현재 세트, 모든 엘리먼트의 추가, 삭제 또는 변경의 반영에 동기화됩니다. 그러나 이 트리들은 애플리케이션의 뷰를 다르게 나타냅니다. 비주얼 트리와 달리 로지컬 트리는 컨트롤의 ContentPresenter 엘리먼트를 확장하지 않습니다. 이것은 같은 객체의 세트를 위한 로지컬 트리와 비주얼 트리간의 일대일 일치성이 없다는 것을 의미합니다. 사실 LogicalTreeHelper 객체의 GetChildren 메소드와 VisualTreeHelper 객체의 GetChild 메소드를 파라미터로 같은 엘리먼트를 사용하여 호출하는 것은 다른 결과를 산출합니다.

로지컬 트리에 관한 더 자세한 정보는 Element Tree를 참고하십시오.

XamlPad로 비주얼 트리를 보기
WPF 툴인 XamlPad는 현재 정의된 XAML 컨텐트와 일치하는 비주얼 트리를 보여주고 탐색하기 위한 옵션을 제공합니다. 비주얼 트리를 표시하기 위해 메뉴 바에 있는 Show Visual Tree 버튼을 클릭하십시오. 다음 그림은 XamlPad의 Visual Tree Explorer패널에서 비주얼 트리 노드에 있는 XAML 컨텐트를 확장한 것입니다.

XamlPad에서 Visual Tree Explorer

Label, TextBoxButton 컨트롤이 XamlPad의 Visual Tree Explorer에서 각각 분리된 비주얼 객체 계층 구조를 표시하는 것에 주목하십시오. 이것은 WPF 컨트롤이 그 컨트롤의 비주얼 트리를 담는 ControlTemplate를 가지고 있기 때문입니다. 명시적으로 컨트롤을 참조하면 그것의 비주얼 계층 구조를 암시적으로 참조하게 됩니다.

비주얼 성능 분석
WPF는 애플리케이션의 런타임 동작 분석과 적용 가능한 성능 최적화의 종류의 결정을 가능케 하는 성능 분석 툴 스위트(suite)를 제공합니다. Visual Profiler 툴은 애플리케이션의 비주얼 트리에 직접 매핑된 성능 데이터의 풍부한 시각적인 뷰를 제공합니다. 이 스크린 샷에서 Visual Profiler의 CPU Usage 섹션은 렌더링이나 레이아웃 같은 오브젝트의 WPF 서비스 사용에 대한 정확한 구분을 제공합니다.

Visual Profiler 화면 출력
사용자 삽입 이미지
WPF 성능 툴에 관한 더 자세한 정보는 Performance Profiling Tools for WPF를 참고하십시오.

비주얼 렌더링 동작

WPF는 비주얼 객체- 보유 모드 그래픽, 벡터 그래픽 및 장치 독립적인 그래픽 - 의 렌더링 동작에 영향을 주는 몇 가지 기능을 소개합니다.

보유 모드 그래픽(Retained Mode Graphics)
비주얼 객체의 역할을 이해하는 핵심 중 하나는 즉시 모드(immediate mode)보유 모드(retained mode) 그래픽 시스템간의 차이를 이해하는 것입니다. 표준 Win32 애플리케이션은 GDI나 GDI+을 사용한 즉시 모드 그래픽 시스템에 기반합니다. 이것은 애플리케이션이 윈도의 크기가 변경되거나 객체가 자신의 시각적인 형태를 변경하는 것 같은 액션이 있을 때 무효화된 클라이언트 영역의 부분을 다시 칠할(repainting) 책임이 있다는 것을 의미합니다.

Win32 렌더링 시퀀스의 다이어그램


이에 비해 WPF는 보유 모드 시스템을 사용합니다. 이것은 시각적인 형태를 가지는 애플리케이션 객체가 직렬화된 드로잉 데이터의 세트를 정의한다는 것을 의미합니다. 일단 드로잉 데이터가 정의되면 시스템은 그 이후의 애플리케이션 객체를 그리기 위한 모든 다시 칠하기 요청에 대해 응답할 책임을 가집니다. 보유 모드 그래픽 시스템의 장점은 그릴 정보가 항상 애플리케이션에 의해 직렬화된 상태를 유지하지만 렌더링할 책임은 시스템에게 넘어간다는 점입니다.

WPF 렌더링 시퀀스의 다이어그램


지능적인 리드로잉
보유 모드 그래픽을 사용하여 얻을 수 있는 가장 큰 이득 중 하나는 WPF가 애플리케이션에서 리드로잉될 필요가 있을 때 효과적으로 최적화 할 수 있다는 것입니다. 심지어 다양한 불투명도의 레벨을 가진 복잡한 신에서도 일반적으로 최적화된 리드로잉를 위한 특별한 동작을 작성할 필요가 없습니다. 이것을 Win32 프로그래밍에서 업데이트 영역 내의 다시 그릴 양을 최소화하여 애플리케이션을 최적화하기 위해 들일 수 있는 엄청난 노력의 낭비와 비교해 보십시오. Win32 애플리케이션에서 다시 그리기 최적화와 관계된 복잡한 유형의 예를 Redrawing in the Update Region에서 참고하십시오.

벡터 그래픽
WPF는 렌더링 데이터 포맷으로써 벡터 그래픽을 사용합니다. 벡터 그래픽스 - Scalable Vector Graphics(SVG), Windows metafiles(.wmf) 및 트루타입 폰트를 포함하는 - 는 렌더링 데이터를 저장하고 원본 그래픽을 사용하여 이미지를 재생성하는 방법을 기술하는 인스트럭션의 목록으로 그것을 전달합니다. 예를 들어 트루타입 폰트는 픽셀을 배열이 아닌 직선, 곡선 및 커맨드의 세트를 기술하는 아웃라인 폰트입니다. 벡터 그래픽의 주요한 장점 중 하나는 크기와 해상도에 관계 없이 스케일(배율 조절) 할 수 있는 능력입니다.

벡터 그래픽과 달리 비트맵 그래픽은 이미지를 나타내는 데 픽셀 단위로 렌더링 데이터를 저장하고, 특정 해상도에 맞춰 미리 렌더링됩니다. 비트맵과 벡터 그래픽 포맷간의 주요한 차이점 중 하나는 원본 이미지에 대한 충실도입니다. 예를 들어 원본 이미지의 크기가 변경되면 비트맵 그래픽 시스템은 이미지를 잡아 늘이는(stretch) 반면 벡터 그래픽 시스템은 이미지의 충실도를 보존하면서 스케일링 합니다.

다음 그림은 300% 리사이즈된 원본 이미지를 보여줍니다. 벡터 그래픽 이미지와는 달리 비트맵 그래픽 이미지의 잡아 늘여져서 왜곡된 모습을 주목하십시오.

래스터와 벡터 그래픽간의 차이점

다음 마크업은 두 Path 엘리먼트의 정의를 보여줍니다. 두번째 엘리먼트는 첫번째 엘리먼트의 드로잉 인스트럭션을 300% 확대하는 데 ScaleTransform을 사용합니다. Path 엘리먼트의 드로잉 인스트럭션이 변형되지 않고 남아있는 것에 주목하십시오.

XAML
<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" />

<Path
  Data="M10,100 C 60,0 100,200 150,100 z"
  Fill="{StaticResource linearGradientBackground}"
  Stroke="Black"
  StrokeThickness="2" >
  <Path.RenderTransform>
    <ScaleTransform ScaleX="3.0" ScaleY="3.0" />
  </Path.RenderTransform>
</Path>

해상도와 장치 독립적 그래픽에 대하여
스크린상에서 텍스트와 그래픽의 크기를 결정하는 두가지 시스템 요인이 있습니다. 바로 해상도(resolution)와 DPI입니다. 해상도는 스크린상에 나타날 픽셀의 수를 기술합니다. 해상도가 높아질 수록 픽셀은 작아지기 때문에 그래픽과 텍스트는 작게 나타납니다. 그래픽은 모니터를 1024 x 768로 설정할 때보다 1600 x 1200으로 설정할 때 더 작게 보일 것입니다.

다른 시스템 설정인 DPI는 스크린 인치(inch)당 픽셀의 크기를 기술합니다. 대부분의 윈도 시스템은 96 DPI를 가지고 있고 스크린 인치는 96 픽셀이라는 것을 의미합니다. DPI 설정을 증가시키는 것은 스크린 인치를 크게 하고 DPI를 감소시키는 것은 스크린 인치를 작게 합니다. 이것은 스크린 인치는 실제의 인치와 같은 크기가 아니라는 것을 의미합니다. 대부분의 시스템에서 대개 그렇습니다. DPI를 증가시키면, 스크린 인치의 크기가 증가되기 때문에 DPI맞춤(DPI-aware) 그래픽과 텍스트는 커집니다. DPI를 증가시키는 것은 특히 높은 해상도에서 텍스트 가독성을 높혀줍니다.

모든 애플리케이션이 DPI맞춤은 아닙니다. 어떤 것은 측정의 주단위로 하드웨어 픽셀을 사용합니다. 이런 애플리케이션에서 시스템 DPI를 변경하는 것은 아무런 효과도 없습니다. 많은 다른 애플리케이션은 폰트 크기를 기술하기 위해 DPI맞춤 단위를 사용하지만 다른 모든 것을 기술하는데에 픽셀을 사용합니다. DPI를 너무 작거나 너무 크게 하는 것은 애플리케이션의 레이아웃 문제를 일으키는 원인이 되기 때문에 애플리케이션의 텍스트는 시스템의 DPI 세팅에 따라 조절되지만 애플리케이션의 UI는 그렇지 않습니다.

이 문제는 WPF를 사용하여 개발된 애플리케이션에서 제거되었습니다. WPF는 하드웨어 픽셀 대신 측정의 주단위로써 장치 독립적인 픽셀을 사용하여 자동 스케일링을 지원합니다. 그래픽과 텍스트는 애플리케이션 개발자의 어떤 추가 작업 없이도 제대로 조절됩니다. 다음 그림은 WPF가 텍스트와 그래픽을 다른 DPI 설정에서 표시하는 방법을 보여줍니다.

다른 DPI 설정에서의 그래픽과 텍스트


VisualTreeHelper 클래스

VisualTreeHelper 클래스는 비주얼 객체 레벨에서 프로그래밍하기 위한 저수준(low-level) 기능을 제공하는 static 헬퍼 클래스이며, 고성능 사용자 정의 컨트롤 개발과 같은 매우 특이한 시나리오에서 유용합니다. 대부분의 경우에서 CanvasTextBlock과 같은 고수준(higer-level) WPF 프레임웍 객체는 매우 융통성있고 사용하기 쉽습니다.

충돌 테스팅
VisualTreeHelper 클래스는 기본 히트 테스트가 필요에 맞지 않을 경우 비주얼 객체상의 충돌 테스팅을 위한 메소드를 제공합니다. 컨트롤이나 그래픽 엘리먼트와 같은 객체의 영역 내에 지오메트리나 포인트 좌표값이 있는지 여부를 결정하기 위하여 VisualTreeHelper에서 HitTest 메소드를 사용할 수 있습니다. 예를 들어 원형의 지오메트리를 둘러싸는 사각형(bounding rectangle) 영역내에 마우스 클릭이 있었는지 여부를 결정하기 위해 히트 테스팅을 사용할 수 있습니다. 또한 직접 작성한 히트 테스트 계산 동작을 위해 기본 히트 테스팅 구현을 오버라이드하는 방법을 택할 수도 있습니다.

히트 테스팅에 관한 더 자세한 정보는 Hit Testing in the Visual Layer를 참고하십시오.

비주얼 트리 열거하기
VisualTreeHelper
클래스는 비주얼 트리의 멤버를 열거하는 기능을 제공합니다. (트리의) 부모를 얻기 위해 GetParent를 호출합니다. 자식을 얻거나 비주얼 객체의 자손을 가리키기 위해 GetChild 메소드를 호출합니다. 이 메소드는 지정된 인덱스에 있는 부모의 자식 Visual을 반환합니다.

다음 예제는 비주얼 객체의 모든 자손을 열거하는 방법을 보여줍니다. 이것은 비주얼 객체 계층 구조의 모든 렌더링 정보를 직렬화하고 싶다면 꼭 사용해야 할 기술입니다.

C#
// 비주얼 객체의 모든 자손을 열거.
static public void EnumVisual(Visual myVisual)
{
    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(myVisual); i++)
    {
        // 지정된 인덱스 값의 자식 비주얼을 얻음.
        Visual childVisual = (Visual)VisualTreeHelper.GetChild(myVisual, i);

        // 자식 비주얼 객체로 처리 수행.

        // 자식 비주얼 객체의 자식을 열거(재귀 호출).
        EnumVisual(childVisual);
    }
}

대부분의 경우에서 로지컬 트리는 WPF 애플리케이션의 엘리먼트를 나타내는데 더 유용합니다. 비록 로지컬 트리를 직접적으로 수정하지 않을 지라도 이 애플리케이션의 뷰는 상속과 이벤트 라우팅을 이해하는데 유용합니다. 비주얼 트리와는 달리 로지컬 트리는 ListItem과 같은 비-비주얼 데이터 객체를 나타낼 수 있습니다. 로지컬 트리에 대한 더 자세한 정보는 Element Tree를 참고하십시오.

VisualTreeHelper 클래스는 비주얼 객체를 둘러싸는 사각형을 반환하는 메소드를 제공합니다. GetContentBounds를 호출하여 비주얼 객체를 둘러싸는 사각형을 반환할 수 있습니다. 또한 GetDescendantBound를 호출하여 비주얼 객체 자신을 포함한 모든 비주얼 객체를 둘러싸는 사각형을 반환할 수 있습니다. 다음 코드는 비주얼 객체와 모든 자신의 자손을 둘러싸는 사각형을 계산하는 방법을 보여줍니다.

C#
// 부모 비주얼 객체와 모든 자손을 둘러싸는 사각형을 반환.
Rect rectBounds = VisualTreeHelper.GetDescendantBounds(parentVisual);

See Also

Reference
Visual
VisualTreeHelper
DrawingVisual

Concepts
Hit Testing in the Visual Layer
Using DrawingVisual Objects
Tutorial: Hosting Visual Objects in a Win32 Application
Optimizing WPF Application Performance
신고
Posted by gongdo


티스토리 툴바