MarqueeLabel.cs
author sl
Tue, 08 Jul 2014 15:49:34 +0200
changeset 6 70b26a1ae93b
parent 5 02716ce36263
child 8 5129c03ab7ba
permissions -rw-r--r--
Marquee now implementing scroll loop properly.
     1 using System;
     2 using System.Collections.Generic;
     3 using System.ComponentModel;
     4 using System.Diagnostics;
     5 using System.Linq;
     6 using System.Text;
     7 using System.Threading.Tasks;
     8 //using System.Timers;
     9 using System.Windows.Forms;
    10 using System.Drawing;
    11 
    12 namespace SharpDisplayManager
    13 {
    14     class MarqueeLabel : Label
    15     {
    16         private bool iOwnTimer;
    17         private StringFormat iStringFormat;
    18         private SolidBrush iBrush;
    19         private SizeF iTextSize;
    20 
    21         [Category("Behavior")]
    22         [Description("How fast is our text scrolling, in pixels per second.")]
    23         [DefaultValue(32)]
    24         [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    25         public int PixelsPerSecond { get; set; }
    26 
    27         [Category("Behavior")]
    28         [Description("Use an internal or an external timer.")]
    29         [DefaultValue(true)]
    30         [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
    31         public bool OwnTimer
    32         {
    33             get
    34             {
    35                 return iOwnTimer;
    36             }
    37             set
    38             {
    39                 iOwnTimer = value;
    40 
    41                 if (iOwnTimer)
    42                 {
    43                     Timer = new Timer();
    44                     Timer.Interval = 10;
    45                     Timer.Tick += new EventHandler(Timer_Tick);
    46                     Timer.Start();
    47                 }
    48                 else
    49                 {
    50                     if (Timer != null)
    51                         Timer.Dispose();
    52                     Timer = null;
    53                 }
    54 
    55             }
    56         }
    57 
    58         private int CurrentPosition { get; set; }
    59         private Timer Timer { get; set; }
    60         private DateTime LastTickTime { get; set; }
    61         private double PixelsLeft { get; set; }
    62         //DateTime a = new DateTime(2010, 05, 12, 13, 15, 00);
    63         //DateTime b = new DateTime(2010, 05, 12, 13, 45, 00);
    64         //Console.WriteLine(b.Subtract(a).TotalMinutes);
    65 
    66         public MarqueeLabel()
    67         {
    68             UseCompatibleTextRendering = true;
    69             //PixelsPerSecond = 32;
    70             LastTickTime = DateTime.Now;
    71             PixelsLeft = 0;
    72             iBrush = new SolidBrush(ForeColor);
    73         }
    74 
    75         public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime)
    76         {
    77             if (!NeedToScroll())
    78             {
    79                 CurrentPosition = 0;
    80                 return;
    81             }
    82 
    83             while (CurrentPosition > (iTextSize.Width))
    84             {
    85                 CurrentPosition -= ((int)iTextSize.Width);
    86             }
    87 
    88             PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond;
    89 
    90             //Keep track of our pixels left over
    91             //PixelsLeft = offset - Math.Truncate(offset);
    92             double offset = Math.Truncate(PixelsLeft);
    93             PixelsLeft -= offset;
    94 
    95             CurrentPosition += Convert.ToInt32(offset);
    96 
    97             /*
    98             if (offset > 1.0)
    99             {
   100                 BackColor = Color.Red;
   101             }
   102             else if (offset==1.0)
   103             {
   104                 if (BackColor != Color.White)
   105                 {
   106                     BackColor = Color.White;
   107                 }
   108 
   109             }
   110             else
   111             {
   112                 //Too slow
   113                 //BackColor = Color.Green;
   114             }*/
   115 
   116             //Only redraw if something has changed
   117             if (offset != 0)
   118             {
   119                 Invalidate();
   120             }
   121         }
   122 
   123         void Timer_Tick(object sender, EventArgs e)
   124         {
   125             DateTime NewTickTime = DateTime.Now;
   126             //
   127             UpdateAnimation(LastTickTime, NewTickTime);
   128             //
   129             LastTickTime = NewTickTime;
   130         }
   131 
   132         private StringFormat GetStringFormatFromContentAllignment(ContentAlignment ca)
   133         {
   134             StringFormat format = new StringFormat();
   135             switch (ca)
   136             {
   137                 case ContentAlignment.TopCenter:
   138                     format.Alignment = StringAlignment.Near;
   139                     format.LineAlignment = StringAlignment.Center;
   140                     break;
   141                 case ContentAlignment.TopLeft:
   142                     format.Alignment = StringAlignment.Near;
   143                     format.LineAlignment = StringAlignment.Near;
   144                     break;
   145                 case ContentAlignment.TopRight:
   146                     format.Alignment = StringAlignment.Near;
   147                     format.LineAlignment = StringAlignment.Far;
   148                     break;
   149                 case ContentAlignment.MiddleCenter:
   150                     format.Alignment = StringAlignment.Center;
   151                     format.LineAlignment = StringAlignment.Center;
   152                     break;
   153                 case ContentAlignment.MiddleLeft:
   154                     format.Alignment = StringAlignment.Center;
   155                     format.LineAlignment = StringAlignment.Near;
   156                     break;
   157                 case ContentAlignment.MiddleRight:
   158                     format.Alignment = StringAlignment.Center;
   159                     format.LineAlignment = StringAlignment.Far;
   160                     break;
   161                 case ContentAlignment.BottomCenter:
   162                     format.Alignment = StringAlignment.Far;
   163                     format.LineAlignment = StringAlignment.Center;
   164                     break;
   165                 case ContentAlignment.BottomLeft:
   166                     format.Alignment = StringAlignment.Far;
   167                     format.LineAlignment = StringAlignment.Near;
   168                     break;
   169                 case ContentAlignment.BottomRight:
   170                     format.Alignment = StringAlignment.Far;
   171                     format.LineAlignment = StringAlignment.Far;
   172                     break;
   173             }
   174 
   175             format.FormatFlags |= StringFormatFlags.NoWrap;
   176             format.FormatFlags |= StringFormatFlags.NoClip;
   177             format.Trimming = StringTrimming.None;
   178 
   179             return format;
   180         }
   181 
   182         protected override void OnForeColorChanged(EventArgs e)
   183         {
   184             //Color has changed recreate our brush
   185             iBrush = new SolidBrush(ForeColor);
   186 
   187             base.OnForeColorChanged(e);
   188         }
   189 
   190 
   191         private void HandleTextSizeChange()
   192         {
   193             //Update text size according to text and font
   194             Graphics g = this.CreateGraphics();
   195             g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   196             iTextSize = g.MeasureString(Text, Font);
   197             iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
   198 
   199             if (NeedToScroll())
   200             {
   201                 //Always align left when scrolling
   202                 iStringFormat.Alignment = StringAlignment.Near;
   203             }
   204         }
   205 
   206         protected override void OnTextChanged(EventArgs e)
   207         {
   208             HandleTextSizeChange();
   209 
   210             base.OnTextChanged(e);
   211         }
   212 
   213         protected override void OnFontChanged(EventArgs e)
   214         {
   215             HandleTextSizeChange();
   216 
   217             base.OnFontChanged(e);
   218         }
   219 
   220         protected override void OnTextAlignChanged(EventArgs e)
   221         {
   222             iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
   223 
   224             base.OnTextAlignChanged(e);
   225 
   226         }
   227 
   228         protected override void OnPaint(PaintEventArgs e)
   229         {
   230             //Disable anti-aliasing
   231             e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
   232             if (NeedToScroll())
   233             {
   234                 //Draw the first one
   235                 e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
   236                 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   237                 //Draw the last one
   238                 e.Graphics.TranslateTransform(iTextSize.Width, 0);
   239                 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   240             }
   241             else
   242             {
   243                 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
   244             }
   245 
   246 
   247 
   248             //DrawText is not working without anti-aliasing. See: stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality
   249             //TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, BackColor, iTextFormatFlags);
   250 
   251             //base.OnPaint(e);
   252         }
   253 
   254         public bool NeedToScroll()
   255         {
   256             //if (Width < e.Graphics.MeasureString(Text, Font).Width)
   257             if (Width < iTextSize.Width)
   258             {
   259                 return true;
   260             }
   261             return false;
   262         }
   263 
   264         protected override void Dispose(bool disposing)
   265         {
   266             if (disposing)
   267             {
   268                 if (Timer != null)
   269                     Timer.Dispose();
   270             }
   271             Timer = null;
   272         }
   273     }
   274 }