Partilhar via


Como Renderizar por Intervalo de Fotogramas Usando CompositionTarget

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

CompositionTarget é uma classe estática que representa a superfície de exibição na qual seu aplicativo está sendo desenhado. O Rendering evento é levantado cada vez 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 o 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 você registra um EventHandler delegado para o 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 manipulador de eventos de renderização para criar conteúdo de desenho personalizado. Esse método manipulador de eventos é chamado uma vez por quadro. Cada vez que o WPF transfere os dados de renderização persistentes da árvore visual para o grafo de cena de composição, o seu método de tratamento de eventos é chamado. Além disso, se alterações na árvore visual obrigarem a atualizações no gráfico da cena de composição, o seu método de manipulador de eventos também será chamado. Observe que seu método manipulador de eventos é chamado após o layout ter sido calculado. No entanto, você pode modificar o layout em seu método 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 manipulador de eventos. Neste caso, a cor de fundo do Canvas é desenhada com um valor da cor com base nas coordenadas do rato. Se moveres o rato dentro do Canvas, a 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 seu desenho personalizado não é independente da taxa de quadros. Dependendo do sistema que você está executando e da carga de trabalho desse sistema, o Rendering evento pode ser chamado um número diferente de vezes por segundo. Para obter informações sobre como determinar a capacidade e o desempenho do hardware gráfico para um dispositivo que executa um aplicativo WPF, consulte Camadas de renderização de gráficos.

Adicionar ou remover um delegado de renderização EventHandler enquanto o evento está sendo acionado será adiado até que o evento termine de disparar. Isso é consistente com a forma como os eventos baseados em MulticastDelegate são tratados no Common Language Runtime (CLR). Observe também que não é garantido que os eventos de renderização sejam chamados em qualquer ordem específica. Se você tiver vários EventHandler delegados que dependem de uma ordem específica, você deve registrar um único Rendering evento e multiplexar os delegados na ordem correta.

Ver também