Freigeben über


Rendern in Pro-Frame-Intervallen mit CompositionTarget

Das WPF-Animationsmodul bietet viele Features zum Erstellen framebasierter Animationen. Es gibt jedoch Anwendungsszenarien, in denen Sie eine präzisere Kontrolle über das Rendering pro Frame benötigen. Das CompositionTarget-Objekt bietet die Möglichkeit, benutzerdefinierte Animationen auf der Grundlage von Pro-Frame-Rückrufen zu erstellen.

CompositionTarget ist eine statische Klasse, die die Anzeigeoberfläche darstellt, auf der Ihre Anwendung gezeichnet wird. Das Rendering-Ereignis wird jedes Mal ausgelöst, wenn die Szene der Anwendung gezeichnet wird. Die Renderingframerate ist die Häufigkeit, mit der die Szene pro Sekunde gezeichnet wird.

Hinweis

Ein vollständiges Codebeispiel mit CompositionTarget finden Sie unter Beispiel für die Verwendung von CompositionTarget.

Beispiel

Das Rendering-Ereignis wird während des WPF-Renderingprozesses ausgelöst. Im folgenden Beispiel wird gezeigt, wie Sie einen EventHandler-Delegaten für die statische Rendering-Methode in CompositionTarget registrieren.

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

Mit der Rendering-Ereignishandlermethode können Sie benutzerdefinierten Zeichnungsinhalt erstellen. Diese Ereignishandlermethode wird einmal pro Frame aufgerufen. Immer, wenn WPF die beibehaltenen Renderingdaten in der visuellen Struktur für die Szenengrafik der Komposition marshallt, wird die Ereignishandlermethode aufgerufen. Zudem wird die Ereignishandlermethode aufgerufen, wenn durch Änderungen an der visuellen Struktur Aktualisierungen zum Szenengraphen erzwungen werden. Beachten Sie, dass Ihre Ereignishandlermethode aufgerufen wird, nachdem das Layout berechnet wurde. Sie können jedoch das Layout in der Ereignishandlermethode ändern, was dazu führt, dass das Layout vor dem Rendern noch einmal berechnet wird.

Das folgende Beispiel zeigt, wie Sie eine benutzerdefinierte Zeichnung in einer CompositionTarget-Ereignishandlermethode bereitstellen können. In diesem Fall wird die Hintergrundfarbe der Canvas mit einem Farbwert erstellt, der auf der Koordinatenposition der Maus basiert. Wenn Sie die Maus innerhalb der Canvasbewegen, ändert sich die Hintergrundfarbe. Darüber hinaus wird die durchschnittliche Bildfrequenz auf Basis der verstrichenen Zeit und der Gesamtanzahl gerenderter Frames berechnet.

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

Möglicherweise stellen Sie fest, dass Ihre benutzerdefinierte Zeichnung mit unterschiedlichen Geschwindigkeiten auf verschiedenen Computern ausgeführt wird. Das liegt daran, dass die benutzerdefinierte Zeichnung nicht von der Bildfrequenz abhängt. Abhängig von dem System, das Sie ausführen, und der Arbeitsauslastung dieses Systems wird das Rendering-Ereignis möglicherweise eine andere Anzahl von Malen pro Sekunde aufgerufen. Informationen zur Ermittlung der Funktionalität der Grafikhardware und der Leistung des Geräts, auf dem eine WPF-Anwendung ausgeführt wird, finden Sie unter Renderingebenen für Grafiken.

Das Hinzufügen bzw. Entfernen eines EventHandler-Delegaten wird während der Auslösung des Ereignisses ausgesetzt. Dies entspricht der Behandlung von MulticastDelegate-basierten Ereignissen in der Common Language Runtime (CLR). Beachten Sie außerdem, dass Renderingereignisse nicht garantiert in einer bestimmten Reihenfolge aufgerufen werden. Wenn Sie über mehrere EventHandler-Delegaten verfügen, die auf einer bestimmten Reihenfolge basieren, registrieren Sie ein einzelnes Rendering-Ereignis und bündeln die Delegaten selbst in der richtigen Reihenfolge.

Siehe auch