sl@0: using System; sl@0: using System.Collections.Generic; sl@0: using System.ComponentModel; sl@0: using System.Diagnostics; sl@0: using System.Linq; sl@0: using System.Text; sl@0: using System.Threading.Tasks; sl@0: //using System.Timers; sl@0: using System.Windows.Forms; sl@0: using System.Drawing; sl@0: sl@0: namespace SharpDisplayManager sl@0: { sl@0: class MarqueeLabel : Label sl@0: { sl@2: private bool iOwnTimer; sl@5: private StringFormat iStringFormat; sl@5: private SolidBrush iBrush; sl@6: private SizeF iTextSize; sl@0: sl@0: [Category("Behavior")] sl@0: [Description("How fast is our text scrolling, in pixels per second.")] sl@0: [DefaultValue(32)] sl@0: [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] sl@0: public int PixelsPerSecond { get; set; } sl@0: sl@2: [Category("Behavior")] sl@2: [Description("Use an internal or an external timer.")] sl@2: [DefaultValue(true)] sl@2: [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)] sl@2: public bool OwnTimer sl@2: { sl@2: get sl@2: { sl@2: return iOwnTimer; sl@2: } sl@2: set sl@2: { sl@2: iOwnTimer = value; sl@2: sl@2: if (iOwnTimer) sl@2: { sl@2: Timer = new Timer(); sl@2: Timer.Interval = 10; sl@2: Timer.Tick += new EventHandler(Timer_Tick); sl@2: Timer.Start(); sl@2: } sl@2: else sl@2: { sl@2: if (Timer != null) sl@2: Timer.Dispose(); sl@2: Timer = null; sl@2: } sl@2: sl@2: } sl@2: } sl@5: sl@2: private int CurrentPosition { get; set; } sl@2: private Timer Timer { get; set; } sl@0: private DateTime LastTickTime { get; set; } sl@0: private double PixelsLeft { get; set; } sl@0: //DateTime a = new DateTime(2010, 05, 12, 13, 15, 00); sl@2: //DateTime b = new DateTime(2010, 05, 12, 13, 45, 00); sl@2: //Console.WriteLine(b.Subtract(a).TotalMinutes); sl@0: sl@0: public MarqueeLabel() sl@0: { sl@0: UseCompatibleTextRendering = true; sl@0: //PixelsPerSecond = 32; sl@0: LastTickTime = DateTime.Now; sl@0: PixelsLeft = 0; sl@5: iBrush = new SolidBrush(ForeColor); sl@0: } sl@0: sl@2: public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime) sl@0: { sl@6: if (!NeedToScroll()) sl@0: { sl@6: CurrentPosition = 0; sl@6: return; sl@6: } sl@6: sl@6: while (CurrentPosition > (iTextSize.Width)) sl@6: { sl@6: CurrentPosition -= ((int)iTextSize.Width); sl@0: } sl@0: sl@2: PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond; sl@0: sl@0: //Keep track of our pixels left over sl@0: //PixelsLeft = offset - Math.Truncate(offset); sl@0: double offset = Math.Truncate(PixelsLeft); sl@0: PixelsLeft -= offset; sl@0: sl@0: CurrentPosition += Convert.ToInt32(offset); sl@0: sl@0: /* sl@0: if (offset > 1.0) sl@0: { sl@0: BackColor = Color.Red; sl@0: } sl@0: else if (offset==1.0) sl@0: { sl@0: if (BackColor != Color.White) sl@0: { sl@0: BackColor = Color.White; sl@0: } sl@0: sl@0: } sl@0: else sl@0: { sl@0: //Too slow sl@0: //BackColor = Color.Green; sl@0: }*/ sl@0: sl@0: //Only redraw if something has changed sl@0: if (offset != 0) sl@0: { sl@0: Invalidate(); sl@0: } sl@2: } sl@0: sl@2: void Timer_Tick(object sender, EventArgs e) sl@2: { sl@5: DateTime NewTickTime = DateTime.Now; sl@2: // sl@2: UpdateAnimation(LastTickTime, NewTickTime); sl@2: // sl@2: LastTickTime = NewTickTime; sl@0: } sl@0: sl@5: private StringFormat GetStringFormatFromContentAllignment(ContentAlignment ca) sl@5: { sl@5: StringFormat format = new StringFormat(); sl@5: switch (ca) sl@5: { sl@5: case ContentAlignment.TopCenter: sl@5: format.Alignment = StringAlignment.Near; sl@5: format.LineAlignment = StringAlignment.Center; sl@5: break; sl@5: case ContentAlignment.TopLeft: sl@5: format.Alignment = StringAlignment.Near; sl@5: format.LineAlignment = StringAlignment.Near; sl@5: break; sl@5: case ContentAlignment.TopRight: sl@5: format.Alignment = StringAlignment.Near; sl@5: format.LineAlignment = StringAlignment.Far; sl@5: break; sl@5: case ContentAlignment.MiddleCenter: sl@5: format.Alignment = StringAlignment.Center; sl@5: format.LineAlignment = StringAlignment.Center; sl@5: break; sl@5: case ContentAlignment.MiddleLeft: sl@5: format.Alignment = StringAlignment.Center; sl@5: format.LineAlignment = StringAlignment.Near; sl@5: break; sl@5: case ContentAlignment.MiddleRight: sl@5: format.Alignment = StringAlignment.Center; sl@5: format.LineAlignment = StringAlignment.Far; sl@5: break; sl@5: case ContentAlignment.BottomCenter: sl@5: format.Alignment = StringAlignment.Far; sl@5: format.LineAlignment = StringAlignment.Center; sl@5: break; sl@5: case ContentAlignment.BottomLeft: sl@5: format.Alignment = StringAlignment.Far; sl@5: format.LineAlignment = StringAlignment.Near; sl@5: break; sl@5: case ContentAlignment.BottomRight: sl@5: format.Alignment = StringAlignment.Far; sl@5: format.LineAlignment = StringAlignment.Far; sl@5: break; sl@5: } sl@5: sl@5: format.FormatFlags |= StringFormatFlags.NoWrap; sl@5: format.FormatFlags |= StringFormatFlags.NoClip; sl@5: format.Trimming = StringTrimming.None; sl@5: sl@5: return format; sl@5: } sl@5: sl@5: protected override void OnForeColorChanged(EventArgs e) sl@5: { sl@6: //Color has changed recreate our brush sl@5: iBrush = new SolidBrush(ForeColor); sl@5: sl@5: base.OnForeColorChanged(e); sl@5: } sl@5: sl@6: sl@6: private void HandleTextSizeChange() sl@6: { sl@6: //Update text size according to text and font sl@6: Graphics g = this.CreateGraphics(); sl@6: g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; sl@6: iTextSize = g.MeasureString(Text, Font); sl@6: iStringFormat = GetStringFormatFromContentAllignment(TextAlign); sl@6: sl@6: if (NeedToScroll()) sl@6: { sl@6: //Always align left when scrolling sl@6: iStringFormat.Alignment = StringAlignment.Near; sl@6: } sl@6: } sl@6: sl@6: protected override void OnTextChanged(EventArgs e) sl@6: { sl@6: HandleTextSizeChange(); sl@6: sl@6: base.OnTextChanged(e); sl@6: } sl@6: sl@6: protected override void OnFontChanged(EventArgs e) sl@6: { sl@6: HandleTextSizeChange(); sl@6: sl@6: base.OnFontChanged(e); sl@6: } sl@6: sl@5: protected override void OnTextAlignChanged(EventArgs e) sl@5: { sl@5: iStringFormat = GetStringFormatFromContentAllignment(TextAlign); sl@5: sl@5: base.OnTextAlignChanged(e); sl@5: sl@5: } sl@5: sl@0: protected override void OnPaint(PaintEventArgs e) sl@0: { sl@0: //Disable anti-aliasing sl@0: e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit; sl@6: if (NeedToScroll()) sl@6: { sl@6: //Draw the first one sl@6: e.Graphics.TranslateTransform(-(float)CurrentPosition, 0); sl@6: e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat); sl@6: //Draw the last one sl@6: e.Graphics.TranslateTransform(iTextSize.Width, 0); sl@6: e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat); sl@6: } sl@6: else sl@6: { sl@6: e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat); sl@6: } sl@6: sl@6: sl@5: sl@5: //DrawText is not working without anti-aliasing. See: stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality sl@5: //TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, BackColor, iTextFormatFlags); sl@5: sl@5: //base.OnPaint(e); sl@0: } sl@0: sl@6: public bool NeedToScroll() sl@6: { sl@6: //if (Width < e.Graphics.MeasureString(Text, Font).Width) sl@6: if (Width < iTextSize.Width) sl@6: { sl@6: return true; sl@6: } sl@6: return false; sl@6: } sl@6: sl@0: protected override void Dispose(bool disposing) sl@0: { sl@0: if (disposing) sl@0: { sl@0: if (Timer != null) sl@0: Timer.Dispose(); sl@0: } sl@0: Timer = null; sl@0: } sl@0: } sl@0: }