다음을 통해 공유


방법: CompositionTarget을 사용하여 프레임별 간격에 렌더링

WPF 애니메이션 엔진은 프레임 기반 애니메이션을 만들기 위한 다양한 기능을 제공합니다. 그러나 프레임당 렌더링을 좀 더 미세하게 제어해야 하는 애플리케이션 시나리오도 있습니다. CompositionTarget 개체는 프레임당 콜백을 기준으로 사용자 지정 애니메이션을 만드는 기능을 제공합니다.

CompositionTarget은 애플리케이션이 그려지는 표시 화면을 나타내는 정적 클래스입니다. Rendering 이벤트는 애플리케이션의 장면이 그려질 때마다 발생합니다. 렌더링 프레임 속도는 장면이 초당 그려지는 횟수입니다.

비고

CompositionTarget을 사용하는 전체 코드 샘플을 보려면 CompositionTarget 샘플 사용을 참조하세요.

예시

Rendering 이벤트는 WPF 렌더링 프로세스 중에 발생합니다. 다음 예제에서는 EventHandler 대리자를 CompositionTarget의 정적 Rendering 메서드에 등록하는 방법을 보여 줍니다.

// Add an event handler to update canvas background color just before it is rendered.
CompositionTarget.Rendering += UpdateColor;
' Add an event handler to update canvas background color just before it is rendered.
AddHandler CompositionTarget.Rendering, AddressOf UpdateColor

렌더링 이벤트 처리기 메서드를 사용하여 사용자 지정 그리기 콘텐츠를 만들 수 있습니다. 이 이벤트 처리기 메서드는 프레임마다 한 번씩 호출됩니다. WPF가 시각적 트리의 지속되는 렌더링 데이터를 컴퍼지션 장면 그래프로 마샬링할 때마다 이벤트 처리기 메서드가 호출됩니다. 또한 시각적 트리를 변경할 때마다 컴퍼지션 장면 그래프가 강제로 업데이트될 경우에도 이벤트 처리기 메서드가 호출됩니다. 이벤트 처리기 메서드는 레이아웃이 계산된 후에 호출됩니다. 그러나 이벤트 처리기 메서드에서 레이아웃을 수정할 수 있습니다. 즉, 레이아웃은 렌더링 전에 한 번 더 계산됩니다.

다음 예제에서는 CompositionTarget 이벤트 처리기 메서드에서 사용자 지정 그리기를 제공하는 방법을 보여 줍니다. 이 경우 Canvas의 배경색은 마우스의 좌표 위치에 따라 색 값으로 그려집니다. Canvas 내부에서 마우스를 이동하면 해당 배경색이 바뀝니다. 또한 현재 경과 시간 및 렌더링된 프레임의 총 수에 따라 평균 프레임 속도가 계산됩니다.

// Called just before frame is rendered to allow custom drawing.
protected void UpdateColor(object sender, EventArgs e)
{
    if (_frameCounter++ == 0)
    {
        // Starting timing.
        _stopwatch.Start();
    }

    // Determine frame rate in fps (frames per second).
    long frameRate = (long)(_frameCounter / this._stopwatch.Elapsed.TotalSeconds);
    if (frameRate > 0)
    {
        // Update elapsed time, number of frames, and frame rate.
        myStopwatchLabel.Content = _stopwatch.Elapsed.ToString();
        myFrameCounterLabel.Content = _frameCounter.ToString();
        myFrameRateLabel.Content = frameRate.ToString();
    }

    // Update the background of the canvas by converting MouseMove info to RGB info.
    byte redColor = (byte)(_pt.X / 3.0);
    byte blueColor = (byte)(_pt.Y / 2.0);
    myCanvas.Background = new SolidColorBrush(Color.FromRgb(redColor, 0x0, blueColor));
}
' Called just before frame is rendered to allow custom drawing.
Protected Sub UpdateColor(ByVal sender As Object, ByVal e As EventArgs)

    If _frameCounter = 0 Then
        ' Starting timing.
        _stopwatch.Start()
    End If
    _frameCounter = _frameCounter + 1

    ' Determine frame rate in fps (frames per second).
    Dim frameRate As Long = CLng(Fix(_frameCounter / Me._stopwatch.Elapsed.TotalSeconds))
    If frameRate > 0 Then
        ' Update elapsed time, number of frames, and frame rate.
        myStopwatchLabel.Content = _stopwatch.Elapsed.ToString()
        myFrameCounterLabel.Content = _frameCounter.ToString()
        myFrameRateLabel.Content = frameRate.ToString()
    End If

    ' Update the background of the canvas by converting MouseMove info to RGB info.
    Dim redColor As Byte = CByte(_pt.X / 3.0)
    Dim blueColor As Byte = CByte(_pt.Y / 2.0)
    myCanvas.Background = New SolidColorBrush(Color.FromRgb(redColor, &H0, blueColor))
End Sub

여러 다른 컴퓨터에서 다른 속도로 사용자 지정 그리기를 실행하는 경우도 있습니다. 사용자 지정 그리기가 프레임 속도와 별개가 아니기 때문입니다. 실행하는 시스템 및 해당 시스템의 워크로드에 따라 초당 다른 횟수만큼 Rendering 이벤트가 호출될 수 있습니다. WPF 애플리케이션을 실행하는 디바이스의 그래픽 하드웨어 기능과 성능 수준을 확인하는 방법에 대한 자세한 내용은 그래픽 렌더링 계층을 참조하세요.

이벤트가 발생하는 동안 렌더링 EventHandler 대리자의 추가 또는 제거 작업은 이벤트 발생이 완료될 때까지 지연됩니다. 이는 MulticastDelegate 기반 이벤트가 CLR(공용 언어 런타임)에서 처리되는 방식과 일치합니다. 또한 렌더링 이벤트가 반드시 특정 순서로 호출되는 것은 아닙니다. 특정 순서에 의존하는 EventHandler 대리자가 여러 개인 경우 단일 Rendering 이벤트를 등록하고 대리자를 올바른 순서로 직접 멀티플렉싱해야 합니다.

참고하십시오