Fixing string measurement issues. Font dialog now properly initialized with
loaded font.
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics;
7 using System.Threading.Tasks;
9 using System.Windows.Forms;
12 namespace SharpDisplayManager
14 class MarqueeLabel : Label
16 private bool iOwnTimer;
17 private StringFormat iStringFormat;
18 private SolidBrush iBrush;
19 private SizeF iTextSize;
20 private SizeF iSeparatorSize;
22 [Category("Appearance")]
23 [Description("Separator in our scrolling loop.")]
25 [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
26 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
27 public string Separator { get; set; }
29 [Category("Behavior")]
30 [Description("How fast is our text scrolling, in pixels per second.")]
32 [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
33 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
34 public int PixelsPerSecond { get; set; }
36 [Category("Behavior")]
37 [Description("Use an internal or an external timer.")]
39 [Browsable(true), EditorBrowsable(EditorBrowsableState.Always)]
40 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
55 Timer.Tick += new EventHandler(Timer_Tick);
68 private int CurrentPosition { get; set; }
69 private Timer Timer { get; set; }
70 private DateTime LastTickTime { get; set; }
71 private double PixelsLeft { get; set; }
72 //DateTime a = new DateTime(2010, 05, 12, 13, 15, 00);
73 //DateTime b = new DateTime(2010, 05, 12, 13, 45, 00);
74 //Console.WriteLine(b.Subtract(a).TotalMinutes);
78 UseCompatibleTextRendering = true;
79 //PixelsPerSecond = 32;
80 LastTickTime = DateTime.Now;
82 iBrush = new SolidBrush(ForeColor);
85 public void UpdateAnimation(DateTime aLastTickTime, DateTime aNewTickTime)
93 while (CurrentPosition > (iTextSize.Width + iSeparatorSize.Width))
95 CurrentPosition -= ((int)(iTextSize.Width + iSeparatorSize.Width));
98 PixelsLeft += aNewTickTime.Subtract(aLastTickTime).TotalSeconds * PixelsPerSecond;
100 //Keep track of our pixels left over
101 //PixelsLeft = offset - Math.Truncate(offset);
102 double offset = Math.Truncate(PixelsLeft);
103 PixelsLeft -= offset;
105 CurrentPosition += Convert.ToInt32(offset);
110 BackColor = Color.Red;
112 else if (offset==1.0)
114 if (BackColor != Color.White)
116 BackColor = Color.White;
123 //BackColor = Color.Green;
126 //Only redraw if something has changed
133 void Timer_Tick(object sender, EventArgs e)
135 DateTime NewTickTime = DateTime.Now;
137 UpdateAnimation(LastTickTime, NewTickTime);
139 LastTickTime = NewTickTime;
142 private StringFormat GetStringFormatFromContentAllignment(ContentAlignment ca)
144 StringFormat format = new StringFormat();
145 format = StringFormat.GenericTypographic;
148 case ContentAlignment.TopCenter:
149 format.Alignment = StringAlignment.Near;
150 format.LineAlignment = StringAlignment.Center;
152 case ContentAlignment.TopLeft:
153 format.Alignment = StringAlignment.Near;
154 format.LineAlignment = StringAlignment.Near;
156 case ContentAlignment.TopRight:
157 format.Alignment = StringAlignment.Near;
158 format.LineAlignment = StringAlignment.Far;
160 case ContentAlignment.MiddleCenter:
161 format.Alignment = StringAlignment.Center;
162 format.LineAlignment = StringAlignment.Center;
164 case ContentAlignment.MiddleLeft:
165 format.Alignment = StringAlignment.Center;
166 format.LineAlignment = StringAlignment.Near;
168 case ContentAlignment.MiddleRight:
169 format.Alignment = StringAlignment.Center;
170 format.LineAlignment = StringAlignment.Far;
172 case ContentAlignment.BottomCenter:
173 format.Alignment = StringAlignment.Far;
174 format.LineAlignment = StringAlignment.Center;
176 case ContentAlignment.BottomLeft:
177 format.Alignment = StringAlignment.Far;
178 format.LineAlignment = StringAlignment.Near;
180 case ContentAlignment.BottomRight:
181 format.Alignment = StringAlignment.Far;
182 format.LineAlignment = StringAlignment.Far;
186 format.FormatFlags |= StringFormatFlags.NoWrap;
187 format.FormatFlags |= StringFormatFlags.NoClip;
188 format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
189 format.Trimming = StringTrimming.None;
194 protected override void OnForeColorChanged(EventArgs e)
196 //Color has changed recreate our brush
197 iBrush = new SolidBrush(ForeColor);
199 base.OnForeColorChanged(e);
203 private void HandleTextSizeChange()
205 //For all string measurements and drawing issues refer to the following article:
206 // http://stackoverflow.com/questions/1203087/why-is-graphics-measurestring-returning-a-higher-than-expected-number
207 //Update text size according to text and font
208 Graphics g = this.CreateGraphics();
209 g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
210 iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
211 iTextSize = g.MeasureString(Text, Font, Int32.MaxValue, iStringFormat);
212 iSeparatorSize = g.MeasureString(Separator, Font, Int32.MaxValue, iStringFormat);
216 //Always align left when scrolling
217 iStringFormat.Alignment = StringAlignment.Near;
221 protected override void OnTextChanged(EventArgs e)
223 HandleTextSizeChange();
225 base.OnTextChanged(e);
228 protected override void OnFontChanged(EventArgs e)
230 HandleTextSizeChange();
232 base.OnFontChanged(e);
235 protected override void OnTextAlignChanged(EventArgs e)
237 iStringFormat = GetStringFormatFromContentAllignment(TextAlign);
239 base.OnTextAlignChanged(e);
243 protected override void OnPaint(PaintEventArgs e)
245 //Disable anti-aliasing
246 e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
250 e.Graphics.TranslateTransform(-(float)CurrentPosition, 0);
251 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
253 e.Graphics.TranslateTransform(iTextSize.Width, 0);
254 e.Graphics.DrawString(Separator, Font, iBrush, ClientRectangle, iStringFormat);
256 e.Graphics.TranslateTransform(iSeparatorSize.Width, 0);
257 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
261 e.Graphics.DrawString(Text, Font, iBrush, ClientRectangle, iStringFormat);
266 //DrawText is not working without anti-aliasing. See: stackoverflow.com/questions/8283631/graphics-drawstring-vs-textrenderer-drawtextwhich-can-deliver-better-quality
267 //TextRenderer.DrawText(e.Graphics, Text, Font, ClientRectangle, ForeColor, BackColor, iTextFormatFlags);
272 public bool NeedToScroll()
274 //if (Width < e.Graphics.MeasureString(Text, Font).Width)
275 if (Width < iTextSize.Width)
282 protected override void Dispose(bool disposing)