Поделиться через


Практическое руководство. Визуализация каждого кадра с помощью CompositionTarget

Подсистема анимации WPF предоставляет множество возможностей для создания покадровой анимации. Однако существуют сценарии применения, в которых необходим детальный контроль над покадровой визуализацией. Объект CompositionTarget предоставляет возможность создания пользовательской анимации на основе покадрового обратного вызова.

CompositionTarget является статическим классом, представляющим поверхность отображения, на которой отрисовывается приложение. Событие Rendering возникает каждый раз при рисовании сцены приложения. Частота кадров отрисовки задает количество отрисовок сцены в секунду.

ПримечаниеПримечание

Полный пример кода с использованием CompositionTarget см. в разделе Пример использования CompositionTarget.

Пример

Событие Rendering активируется во время процесса визуализации WPF. В следующем примере показана регистрация делегата EventHandler в статическом методе Rendering для CompositionTarget.

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

Можно использовать собственный метод обработчика событий визуализации для создания пользовательского графического содержимого. Этот метод обработчика событий вызывается один раз за кадр. Каждый раз, когда WPF маршалирует сохраненные данные визуализации в визуальном дереве через граф сцены, вызывается метод обработчика событий. Кроме того, метод обработчика событий вызывается в случае, если изменения визуального дерева принудительно обновляют граф сцены. Обратите внимание, что метод обработчика событий вызывается после вычисления макета. Однако можно изменить макет в методе обработчика событий, что означает повторное вычисление макета перед визуализацией.

В следующем примере показано, как можно предоставить пользовательское рисование в методе обработчика событий CompositionTarget. В этом случае цвет фона Canvas рисуется значением цвета на основе координат указателя мыши. Перемещение указателя мыши внутри Canvas изменяет цвет его фона. Кроме того, вычисляется средняя частота кадров на основе текущего значения прошедшего времени и общего числа визуализированных кадров.

        ' 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
// 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));
}

Можно обнаружить, что пользовательское рисование выполняется с разными скоростями на разных компьютерах. Это обусловлено тем, что пользовательское рисование зависит от частоты кадров. В зависимости от используемой системы и рабочей нагрузки на эту систему число вызовов события Rendering в секунду может варьировать. Сведения об определении аппаратных возможностей и производительности графического устройства, на котором выполняется приложение WPF, см. в разделе Уровни графической отрисовки.

Добавление или удаление делегата визуализации EventHandler во время срабатывания события будет отложено до завершения срабатывания события. Это согласуется с порядком обработки событий на основе MulticastDelegate в общеязыковой среде выполнения (CLR). Также обратите внимание на то, что какой-либо определенный порядок вызова событий визуализации не гарантируется. Если имеется несколько делегатов EventHandler, зависимых от определенного порядка, следует вручную зарегистрировать одно событие Rendering и мультиплексировать делегаты в правильном порядке.

См. также

Ссылки

CompositionTarget

Основные понятия

Общие сведения об отрисовке графики в WPF