如何提高此控件的性能

本文关键字:性能 控件 何提高 | 更新日期: 2023-09-27 18:29:49

我需要一个项目的字幕,经过多次谷歌搜索和反复尝试,我创建了一个。但是,动画本身有点抖动。我需要一些关于如何提高性能的建议。谢谢p.s.有些代码可能是多余的。。。

public class Marquee : Canvas
{
    static Marquee()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(Marquee), new FrameworkPropertyMetadata(typeof(Marquee)));
    }
    private IList<string> _lines = new List<string>();
    private IList<string> Lines
    {
        get
        {
            return _lines;
        }
        set
        {
            _lines = value;
        }
    }
    public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontSize.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontSizeProperty =
        DependencyProperty.Register("FontSize", typeof(double), typeof(Marquee));
    public Brush FontBrush
    {
        get { return (Brush)GetValue(FontBrushProperty); }
        set { SetValue(FontBrushProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontBrush.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontBrushProperty =
        DependencyProperty.Register("FontBrush", typeof(Brush), typeof(Marquee));
    public string SourceFile { get; set; }
    List<RenderTargetBitmap> _images = new List<RenderTargetBitmap>();
    private void CreateBitmaps()
    {
        foreach (var line in Lines)
        {
            FormattedText ft = new FormattedText(line,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(FontFamily.Source),
            FontSize,
            FontBrush);
            if (ft.Height == 0 || ft.Width == 0)
                continue;
            DrawingVisual drawingVisual = new DrawingVisual();
            DrawingContext drawingContext = drawingVisual.RenderOpen();
            drawingContext.DrawText(ft, new Point(0, 0));
            drawingContext.Close();
            RenderTargetBitmap bmp = new RenderTargetBitmap((int)ft.Width, (int)ft.Height, 72, 72, PixelFormats.Pbgra32);
            bmp.Render(drawingVisual);
            bmp.Freeze();
            _images.Add(bmp);
        }
    }
    private int nextImgIndex = 0;
    private Image _Image;
    private void GetNextImage()
    {
        if (_images.Count == 0)
            return;
        if (nextImgIndex >= _images.Count)
            nextImgIndex = 0;
        _Image.Source = _images.ElementAt(nextImgIndex++);
    }
    private string _curStr = null;
    private string CurrentString
    {
        get
        {
            return _curStr;
        }
        set
        {
            _curStr = value;
        }
    }
    TextBlock _textBlock = new TextBlock();
    DispatcherTimer timer;
    public Marquee()
    {
        Loaded += Marquee_Loaded;
        FontSize = 12;
        FontBrush = Brushes.Black;
        if (Rate == 0d)
        {
            Rate = 150d;
        }
        this.CacheMode = new BitmapCache(2);
        FontBrush.Freeze();
        _Image = new Image();
        _Image.CacheMode = new BitmapCache();
        _Image.ClipToBounds = false;
        FontFamily = new FontFamily("Calibri");
        this.Children.Add(_Image);
    }
    void Marquee_Loaded(object sender, RoutedEventArgs e)
    {
        ReadFile();
        CreateBitmaps();
        CreateAnimation();
        //throw new NotImplementedException();
    }

    //[ValueConversion(typeof(string), typeof(TimeSpan))]
    //public class StringFormatConverter : IValueConverter
    //{
    //    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    //    {
    //        string[] vals = ((string)value).Split(new[] { ':' });
    //        if (vals.Count() != 3)
    //            throw new FormatException(string.Format("Invalid timespan format : {0}", value));
    //        return new TimeSpan(int.Parse(vals[0]), int.Parse(vals[1]), int.Parse(vals[2]));
    //    }
    //    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    //    {
    //        throw new NotImplementedException();
    //    }
    //}
    DoubleAnimation anim;
    TranslateTransform transform;
    Duration duration;
    public double Rate { get; set; }
    void CreateAnimation()
    {
        if (CurrentString == null)
            return;
        GetNextImage();
        transform = new TranslateTransform(Application.Current.MainWindow.ActualWidth, 0);
        _Image.RenderTransform = transform;
        var width = _Image.Source.Width;
        double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;
        duration = new Duration(TimeSpan.FromSeconds(secs));
        anim = new DoubleAnimation(-width, duration);
        anim.Completed += anim_Completed;
        transform.BeginAnimation(TranslateTransform.XProperty, anim);
    }
    void anim_Completed(object sender, EventArgs e)
    {
        CreateAnimation();
    }
    double MeasureStringLength(string text)
    {
        if (text == null)
            return 0;
        FormattedText ft = new FormattedText(text,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(_textBlock.FontFamily.ToString()),
            FontSize,
            FontBrush);
        return ft.Width;
    }

    public FontFamily FontFamily
    {
        get { return (FontFamily)GetValue(FontFamilyProperty); }
        set { SetValue(FontFamilyProperty, value); }
    }
    // Using a DependencyProperty as the backing store for FontFamily.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontFamilyProperty =
        DependencyProperty.Register("FontFamily", typeof(FontFamily), typeof(Marquee));
    FormattedText GetFormattedText(string text)
    {
        if (text == null)
            return null;
        FormattedText ft = new FormattedText(text,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(_textBlock.FontFamily.ToString()),
            FontSize,
            FontBrush);
        return ft;
    }
    void ReadFile()
    {
        if (SourceFile == null)
            return;
        StreamReader fR = new StreamReader(SourceFile);
        string line;
        while ((line = fR.ReadLine()) != null)
        {
            Lines.Add(line);
        }
        if (Lines.Count > 0)
            CurrentString = Lines[0];
    }
}

如何提高此控件的性能

我以以下方式修改了您的控件(删除变换动画,使用直接渲染而不是渲染到图像缓存):

public static readonly DependencyProperty OffsetProperty = DependencyProperty.Register("Offset", typeof(double),
    typeof(Marquee), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.AffectsRender));
//
public double Offset {
    get { return (double)GetValue(OffsetProperty); }
}
protected override void OnRender(DrawingContext dc) {
    dc.DrawText(currentText, new Point(Offset, 0)); // direct render
}
int nextTextIndex = 0;
FormattedText currentText;
void GetNextText() {
    if(formattedTexts.Count == 0) return;
    currentText = formattedTexts[(nextTextIndex++) % formattedTexts.Count];
}
void CreateAnimation() {
    if(CurrentString == null)
        return;
    GetNextText();
    double width = currentText.Width;
    double secs = (Application.Current.MainWindow.ActualWidth + width) / Rate;
    duration = new Duration(TimeSpan.FromSeconds(secs));
    anim = new DoubleAnimation(0, -width, duration);
    anim.Completed += anim_Completed;
    BeginAnimation(OffsetProperty, anim);
}
//
void anim_Completed(object sender, EventArgs e) {
    anim.Completed -= anim_Completed;
    CreateAnimation();
}
List<FormattedText> formattedTexts = new List<FormattedText>();
void CreateTexts() {
    foreach(var line in Lines) {
        FormattedText ft = new FormattedText(line,
            System.Globalization.CultureInfo.CurrentUICulture,
            System.Windows.FlowDirection.LeftToRight,
            new Typeface(FontFamily.Source),
            FontSize,
            FontBrush);
        if(ft.Height == 0 || ft.Width == 0)
            continue;
        formattedTexts.Add(ft);
    }
}

现在它对我来说更流畅了。