1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/Server/MarqueeLabel.cs Tue Aug 12 20:55:50 2014 +0200
1.3 @@ -0,0 +1,293 @@
1.4 +using System;
1.5 +using System.Collections.Generic;
1.6 +using System.ComponentModel;
1.7 +using System.Diagnostics;
1.8 +using System.Linq;
1.9 +using System.Text;
1.10 +using System.Threading.Tasks;
1.11 +//using System.Timers;
1.12 +using System.Windows.Forms;
1.13 +using System.Drawing;
1.14 +
1.15 +namespace SharpDisplayManager
1.16 +{
1.17 + [System.ComponentModel.DesignerCategory("Code")]
1.18 + public class MarqueeLabel : Label
1.19 + {
1.20 + private bool iOwnTimer;
1.21 + private StringFormat iStringFormat;
1.22 + private SolidBrush iBrush;
1.23 + private SizeF iTextSize;
1.24 + private SizeF iSeparatorSize;
1.25 +
1.26 + [Category("Appearance")]
1.27 + [Description("Separator in our scrolling loop.")]
1.28 + [DefaultValue(" | ")]
1.29 + [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
1.30 + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
1.31 + public string Separator { get; set; }
1.32 +
1.33 + [Category("Behavior")]
1.34 + [Description("How fast is our text scrolling, in pixels per second.")]
1.35 + [DefaultValue(32)]
1.36 + [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
1.37 + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
1.38 + public int PixelsPerSecond { get; set; }
1.39 +
1.40 + [Category("Behavior")]
1.41 + [Description("Use an internal or an external timer.")]
1.42 + [DefaultValue(true)]
1.43 + [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
1.44 + [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
1.45 + public bool OwnTimer
1.46 + {
1.47 + get
1.48 + {
1.49 + return iOwnTimer;
1.50 + }
1.51 + set
1.52 + {
1.53 + iOwnTimer = value;
1.54 +
1.55 + if (iOwnTimer)
1.56 + {
1.57 + Timer = new Timer();
1.58 + Timer.Interval = 10;
1.59 + Timer.Tick += new EventHandler(Timer_Tick);
1.60 + Timer.Start();
1.61 + }
1.62 + else
1.63 + {
1.64 + if (Timer != null)
1.65 + Timer.Dispose();
1.66 + Timer = null;
1.67 + }
1.68 +
1.69 + }
1.70 + }
1.71 +
1.72 + private int CurrentPosition { get; set; }
1.73 + private Timer Timer { get; set; }
1.74 + private DateTime LastTickTime { get; set; }
1.75 + private double PixelsLeft { get; set; }
1.76 + //DateTime a = new DateTime(2010, 05, 12, 13, 15, 00);
1.77 + //DateTime b = new DateTime(2010, 05, 12, 13, 45, 00);
1.78 + //Console.WriteLine(b.Subtract(a).TotalMinutes);
1.79 +
1.80 + public MarqueeLabel()
1.81 + {
1.82 + UseCompatibleTextRendering = true;
1.83 + //PixelsPerSecond = 32;
1.84 + LastTickTime = DateTime.Now;
1.85 + PixelsLeft = 0;
1.86 + iBrush = new SolidBrush(ForeColor);
1.87 + }
1.88 +
1.89 + public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime)
1.90 + {
1.91 + if (!NeedToScroll())
1.92 + {
1.93 + CurrentPosition = 0;
1.94 + return;
1.95 + }
1.96 +
1.97 + while (CurrentPosition > (iTextSize.Width + iSeparatorSize.Width))
1.98 + {
1.99 + CurrentPosition -= ((int)(iTextSize.Width + iSeparatorSize.Width));
1.100 + }
1.101 +
1.102 + PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond;
1.103 +
1.104 + //Keep track of our pixels left over
1.105 + //PixelsLeft = offset - Math.Truncate(offset);
1.106 + double offset = Math.Truncate(PixelsLeft);
1.107 + PixelsLeft -= offset;
1.108 +
1.109 + CurrentPosition += Convert.ToInt32(offset);
1.110 +
1.111 + /*
1.112 + if (offset > 1.0)
1.113 + {
1.114 + BackColor = Color.Red;
1.115 + }
1.116 + else if (offset==1.0)
1.117 + {
1.118 + if (BackColor != Color.White)
1.119 + {
1.120 + BackColor = Color.White;
1.121 + }
1.122 +
1.123 + }
1.124 + else
1.125 + {
1.126 + //Too slow
1.127 + //BackColor = Color.Green;
1.128 + }*/
1.129 +
1.130 + //Only redraw if something has changed
1.131 + if (offset != 0)
1.132 + {
1.133 + Invalidate();
1.134 + }
1.135 + }
1.136 +
1.137 + void Timer_Tick(object sender, EventArgs e)
1.138 + {
1.139 + DateTime NewTickTime = DateTime.Now;
1.140 + //
1.141 + UpdateAnimation(LastTickTime, NewTickTime);
1.142 + //
1.143 + LastTickTime = NewTickTime;
1.144 + }
1.145 +
1.146 + private StringFormat GetStringFormatFromContentAllignment(ContentAlignment ca)
1.147 + {
1.148 + StringFormat format = new StringFormat();
1.149 + format = StringFormat.GenericTypographic;
1.150 + switch (ca)
1.151 + {
1.152 + case ContentAlignment.TopCenter:
1.153 + format.Alignment = StringAlignment.Near;
1.154 + format.LineAlignment = StringAlignment.Center;
1.155 + break;
1.156 + case ContentAlignment.TopLeft:
1.157 + format.Alignment = StringAlignment.Near;
1.158 + format.LineAlignment = StringAlignment.Near;
1.159 + break;
1.160 + case ContentAlignment.TopRight:
1.161 + format.Alignment = StringAlignment.Near;
1.162 + format.LineAlignment = StringAlignment.Far;
1.163 + break;
1.164 + case ContentAlignment.MiddleCenter:
1.165 + format.Alignment = StringAlignment.Center;
1.166 + format.LineAlignment = StringAlignment.Center;
1.167 + break;
1.168 + case ContentAlignment.MiddleLeft:
1.169 + format.Alignment = StringAlignment.Center;
1.170 + format.LineAlignment = StringAlignment.Near;
1.171 + break;
1.172 + case ContentAlignment.MiddleRight:
1.173 + format.Alignment = StringAlignment.Center;
1.174 + format.LineAlignment = StringAlignment.Far;
1.175 + break;
1.176 + case ContentAlignment.BottomCenter:
1.177 + format.Alignment = StringAlignment.Far;
1.178 + format.LineAlignment = StringAlignment.Center;
1.179 + break;
1.180 + case ContentAlignment.BottomLeft:
1.181 + format.Alignment = StringAlignment.Far;
1.182 + format.LineAlignment = StringAlignment.Near;
1.183 + break;
1.184 + case ContentAlignment.BottomRight:
1.185 + format.Alignment = StringAlignment.Far;
1.186 + format.LineAlignment = StringAlignment.Far;
1.187 + break;
1.188 + }
1.189 +
1.190 + format.FormatFlags |= StringFormatFlags.NoWrap;
1.191 + format.FormatFlags |= StringFormatFlags.NoClip;
1.192 + format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
1.193 + format.Trimming = StringTrimming.None;
1.194 +
1.195 + return format;
1.196 + }
1.197 +
1.198 + protected override void OnForeColorChanged(EventArgs e)
1.199 + {
1.200 + //Color has changed recreate our brush
1.201 + iBrush = new SolidBrush(ForeColor);
1.202 +
1.203 + base.OnForeColorChanged(e);
1.204 + }
1.205 +
1.206 +
1.207 + private void HandleTextSizeChange()
1.208 + {
1.209 + //For all string measurements and drawing issues refer to the following article:
1.210 + // http://stackoverflow.com/questions/1203087/why-is-graphics-measurestring-returning-a-higher-than-expected-number
1.211 + //Update text size according to text and font
1.212 + Graphics g = this.CreateGraphics();
1.213 + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
1.214 + iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
1.215 + iTextSize = g.MeasureString(Text, Font, Int32.MaxValue, iStringFormat);
1.216 + iSeparatorSize = g.MeasureString(Separator, Font, Int32.MaxValue, iStringFormat);
1.217 +
1.218 + if (NeedToScroll())
1.219 + {
1.220 + //Always align left when scrolling
1.221 + iStringFormat.Alignment = StringAlignment.Near;
1.222 + }
1.223 + }
1.224 +
1.225 + protected override void OnTextChanged(EventArgs e)
1.226 + {
1.227 + HandleTextSizeChange();
1.228 +
1.229 + base.OnTextChanged(e);
1.230 + }
1.231 +
1.232 + protected override void OnFontChanged(EventArgs e)
1.233 + {
1.234 + HandleTextSizeChange();
1.235 +
1.236 + base.OnFontChanged(e);
1.237 + }
1.238 +
1.239 + protected override void OnTextAlignChanged(EventArgs e)
1.240 + {
1.241 + iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
1.242 +
1.243 + base.OnTextAlignChanged(e);
1.244 +
1.245 + }
1.246 +
1.247 + protected override void OnPaint(PaintEventArgs e)
1.248 + {
1.249 + //Disable anti-aliasing
1.250 + e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
1.251 + if (NeedToScroll())
1.252 + {
1.253 + //Draw the first one
1.254 + e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
1.255 + e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
1.256 + //Draw separator
1.257 + e.Graphics.TranslateTransform(iTextSize.Width, 0);
1.258 + e.Graphics.DrawString(Separator, Font, iBrush, ClientRectangle, iStringFormat);
1.259 + //Draw the last one
1.260 + e.Graphics.TranslateTransform(iSeparatorSize.Width, 0);
1.261 + e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
1.262 + }
1.263 + else
1.264 + {
1.265 + e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
1.266 + }
1.267 +
1.268 +
1.269 +
1.270 + //DrawText is not working without anti-aliasing. See: stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality
1.271 + //TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, BackColor, iTextFormatFlags);
1.272 +
1.273 + //base.OnPaint(e);
1.274 + }
1.275 +
1.276 + public bool NeedToScroll()
1.277 + {
1.278 + //if (Width < e.Graphics.MeasureString(Text, Font).Width)
1.279 + if (Width < iTextSize.Width)
1.280 + {
1.281 + return true;
1.282 + }
1.283 + return false;
1.284 + }
1.285 +
1.286 + protected override void Dispose(bool disposing)
1.287 + {
1.288 + if (disposing)
1.289 + {
1.290 + if (Timer != null)
1.291 + Timer.Dispose();
1.292 + }
1.293 + Timer = null;
1.294 + }
1.295 + }
1.296 +}