Compartilhar via


Como renderizar em um intervalo por quadro usando CompositionTarget

O mecanismo de animação do WPF fornece muitos recursos para criar animação baseada em quadros. No entanto, há cenários de aplicativo nos quais você precisa de um controle mais refinado sobre a renderização por quadro. O CompositionTarget objeto permite criar animações personalizadas com base em um callback por frame.

CompositionTarget é uma classe estática que representa a superfície de exibição na qual seu aplicativo está sendo desenhado. O Rendering evento é gerado sempre que a cena do aplicativo é desenhada. A taxa de quadros de renderização é o número de vezes que a cena é desenhada por segundo.

Observação

Para obter um exemplo de código completo usando CompositionTarget, consulte Usando o exemplo CompositionTarget.

Exemplo

O Rendering evento é acionado durante o processo de renderização do WPF. O exemplo a seguir mostra como registrar um EventHandler delegado no método estático Rendering em CompositionTarget.

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

Você pode usar seu método de manipulador de eventos de renderização para criar conteúdo de desenho personalizado. Esse método de manipulador de eventos é chamado uma vez por quadro. Cada vez que o WPF transfere os dados de renderização persistentes na árvore visual para o grafo de composição de cena, o método do seu manipulador de eventos é chamado. Além disso, se as alterações na árvore visual exigirem atualizações no grafo de cena de composição, o método do manipulador de eventos também será chamado. Observe que o método do manipulador de eventos é chamado após a computação do layout. No entanto, você pode modificar o layout em seu método de manipulador de eventos, o que significa que o layout será computado mais uma vez antes da renderização.

O exemplo a seguir mostra como você pode fornecer desenho personalizado em um CompositionTarget método de manipulador de eventos. Nesse caso, a cor de fundo do Canvas é desenhada com um valor de cor com base na posição de coordenada do mouse. Se você mover o mouse dentro do Canvas, sua cor de fundo muda. Além disso, a taxa média de quadros é calculada, com base no tempo decorrido atual e no número total de quadros renderizados.

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

Você pode descobrir que seu desenho personalizado é executado em velocidades diferentes em computadores diferentes. Isso ocorre porque o desenho personalizado não é independente da taxa de quadros. Dependendo do sistema em execução e da carga de trabalho desse sistema, o Rendering evento pode ser chamado de um número diferente de vezes por segundo. Para obter informações sobre como determinar a funcionalidade de hardware gráfico e o desempenho de um dispositivo que executa um aplicativo WPF, consulte Camadas de Renderização de Gráficos.

Adicionar ou remover um delegado de EventHandler de renderização durante a execução do evento será postergado até o término do evento. Isso é consistente com a maneira como os eventos baseados em MulticastDelegate são tratados no CLR (Common Language Runtime). Observe também que não há garantia de que os eventos de renderização sejam chamados em nenhuma ordem específica. Se você tiver vários EventHandler delegados que dependem de uma ordem específica, registre um único Rendering evento e multiplexe os delegados na ordem correta por conta própria.

Consulte também