using System; using System.Collections.Generic; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Timers; using System.Windows; using System.Windows.Controls; using System.Windows.Media; namespace ProjetTheAlone.ViewModel { public class TextDefilant : BasePropriete { public event TickHandler Tick; public EventArgs e = null; public delegate void TickHandler(object o, EventArgs e); public Timer aTimer; public TextBlock textContainer; char[] textAfficherBuffer; string textAfficher; public string TextAfficher { set { fillBuffer(value); textAfficher = value; } get { return new string(textAfficherBuffer); } } public TextDefilant(TextBlock tb, string text, int timeMs) { this.textContainer = tb; TextAfficher = text; SetTimer(timeMs); aTimer.Enabled = true; } private void SetTimer(int timeMs) { // Create a timer with a two second interval. aTimer = new System.Timers.Timer(timeMs); // Hook up the Elapsed event for the timer. aTimer.Elapsed += OnTimedEvent; aTimer.AutoReset = true; } private void OnTimedEvent(Object source, ElapsedEventArgs e) { textAfficherBuffer = RotateChar(textAfficherBuffer); Tick?.Invoke(this, null); OnPropertyChanged("TextAfficher"); } private void fillBuffer(string text) { char[] charToTrim = { '\r', '\n' }; text = text.Trim(charToTrim); double WTB = textContainer.ActualWidth; //With of textBlock container double WT = MeasureString(text).Width; //With of Text double WS = MeasureString(" ").Width; //With of whiteSpace int nbSp = (int)Math.Ceiling((WTB-WT) / WS); //number of space need to fill textBlock char[] spText = new string(' ', nbSp).ToCharArray(); this.textAfficherBuffer = new char[nbSp + text.ToCharArray().Length]; Array.Copy(text.ToCharArray(), 0, this.textAfficherBuffer, 0, text.Length); Array.Copy(spText, 0, this.textAfficherBuffer, text.Length, spText.Length); } private char[] RotateChar(char[] txt) { char[] oldTxt = txt; char[] newTxt = new char[oldTxt.Length]; char fc = txt[0]; for (int i = oldTxt.Length - 1; i > 0; i--) newTxt[((i+1)%oldTxt.Length)] = oldTxt[i]; newTxt[1] = fc; return newTxt; } //https://stackoverflow.com/questions/9264398/how-to-calculate-wpf-textblock-width-for-its-known-font-size-and-characters private Size MeasureString(string candidate) { FormattedText formattedText = null; this.textContainer.Dispatcher.Invoke(() => { formattedText = new FormattedText( candidate, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(this.textContainer.FontFamily, this.textContainer.FontStyle, this.textContainer.FontWeight, this.textContainer.FontStretch), this.textContainer.FontSize, Brushes.Black, new NumberSubstitution(), (TextFormattingMode)1); }); return new Size(formattedText.WidthIncludingTrailingWhitespace, formattedText.Height); } } }