2012-04-03 6 views
0

Ich brauchte ein Marquee für ein Projekt und nach vielem Googeln und Versuch und Irrtum habe ich einen erstellt. Die Animation selbst ist jedoch etwas nervös. Ich brauche einige Hinweise, wie ich die Leistung verbessern kann. Vielen Dank. p.s. Einige der Code kann redundant sein ...Wie kann die Leistung dieses Steuerelements verbessert werden?

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]; 
    } 
} 
+0

Haben Sie versucht, die Anwendung zu profilieren? –

Antwort

0

ich Ihre Steuerung auf die folgende Weise modifiziert bin (Entfernen der Animation verwandeln, Direct Rendering anstelle von Rendern Bild-Cache):

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

Jetzt ist es für mich glatter.

Verwandte Themen