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