Gewusst wie: Rendern in Pro-Frame-Intervallen mit CompositionTarget
Die WPF-Animations-Engine stellt zahlreiche Funktionen zum Erstellen framebasierter Animationen bereit. In manchen Anwendungsszenarios müssen Sie das Rendering jedoch pro Frame detaillierter steuern können. 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 die Anwendung gezeichnet wird. Das Rendering-Ereignis wird jedes Mal ausgelöst, wenn die Szene der Anwendung gezeichnet wird. Die Renderingbildfrequenz gibt an, wie häufig die Szene pro Sekunde gezeichnet wird.
Hinweis
Ein vollständiges Codebeispiel für die Verwendung von 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 der Szenengrafik erzwungen werden. Beachten Sie, dass die Ereignishandlermethode aufgerufen wird, nachdem das Layout berechnet wurde. Sie können das Layout jedoch in der Ereignishandlermethode ändern. In diesem Fall wird das Layout vor dem Rendern erneut berechnet.
Im folgenden Beispiel wird gezeigt, wie Sie in einer CompositionTarget-Ereignishandlermethode benutzerdefinierte Zeichnungen 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 auf der Canvas bewegen, ä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 die benutzerdefinierte Zeichnung auf verschiedenen Computern mit unterschiedlicher Geschwindigkeit ausgeführt wird. Das liegt daran, dass die benutzerdefinierte Zeichnung von der Bildfrequenz abhängt. Je nach Betriebssystem und Workload wird das Rendering-Ereignis unterschiedlich oft pro Sekunde aufgerufen. Informationen zur Ermittlung der Grafikleistung eines 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 die Reihenfolge, in der die Renderingereignisse aufgerufen werden, nicht festgelegt werden kann. 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.
Weitere Informationen
.NET Desktop feedback