zoukankan      html  css  js  c++  java
  • ToolStripStatusRollingLabel——滚动显示状态栏标签

    前    注:

    这是自己平时根据自己需要写的一些小代码,未必对各看官有用。另外,这是根据个人想法而写,未必严谨和符合设计原则,若有任何不妥之处,还请不吝赐教。

    说    明:

    本文描述一个可滚动显示文本信息的状态栏标签控件。起因是某天领导说某些信息应该更醒目,让用户更容易注意到。于是就花了半天的时间做了这个东西。

    基本的思路是用定时器每隔一段时间重绘文本,使其显示在控件的不同位置。

    已经实现了关于滚动速度、精细度的控制功能,已经实现由右至左滚动显示的滚动方式。

    使用方式:将向状态栏添加标签,再到设计器代码中将标签类型改为ToolStripStatusRollingLabel。

    设计要点:

    1、由于ToolStripStatusLabel无法设置文本的显示位置,因此需要重载OnPaint来更改文本的绘制逻辑。为了避免完全重绘控件,重写的OnPaint函数先调用ToolStripStatusLabel.OnPaint,再使用GDI在控件上绘制文本。

    为了提供与ToolStripStatusLabel类似的使用接口,保留Text作为新控件中设置需滚动显示的文本内容的属性。由于ToolStripStatusLabel.OnPaint同样会绘制文本,若不特殊处理,控件将会同时显示一个滚动的文本和一个静止的文本。

    因此,需要重载Text属性,将需要显示的文本内容另设变量存储(用于在重写的OnPaint中使用),并且使Text属性在运行时为空。另一方面,为保证用户体验,又需要Text属性在设计器中的值与所设置的值一致。这就是重写的Text属性的get访问器需要判断DesignMode的原因。

    2、滚动的速度与精细度通过两个属性组合来控制:一、RollSpeed,设置定时器每次动作时,文本显示位置与上一次显示位置之间的距离;二、RedrawTimeSpan,设置定时器触发的时间间隔。RedrawTimeSpan越小,RoolSpeed越大,滚动的速度越快;RedrawTimeSpan越小,RoolSpeed越小,滚动的精细度越高。

    3、控件的滚动样式由文本在控件上的显示位置的变化规律决定。便于扩展滚动样式,计算文本显示位置的逻辑被抽取出来,形成一个单独的接口IControlDataRollOffsetGenerater。

    4、IControlDataRollOffsetGenerater提供获取一个在某个区间内滚动的数值的接口。对我能想到的所有滚动样式,文本的每个显示位置均可由控件宽度、文本宽度及上次显示位置和每次的偏移量确定。在此接口中,这些数据分别由WindowWidth、DataWidth、Offset和Speed表示。

    5、特殊的滚动效果:文本朝某个方向滚动,消失的部分文本从控件的另一端显示出来。可以这样实现:将用户要显示的文本用空白拼接起来显示,空白的长度等于控件宽度与文本长度的差。当然,这要求文本长度不能超过控件宽度。

    结构图  :

    未命名

    源代码  :

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    namespace CommonLibrary.ExtendedControl
    {
        /// <summary>
        /// 滚动显示的状态栏标签类
        /// </summary>
        public class ToolStripStatusRollingLabel : ToolStripStatusLabel
        {
            public ToolStripStatusRollingLabel()
            {
                StringRect.X = this.Padding.Left;
                StringRect.Y = this.Padding.Top;
                StringRect.Height = Size.Height - Padding.Top - Padding.Bottom;
    
                Brush = new SolidBrush(this.ForeColor);
                ControlDataRollOffsetGenerater = ControlDataRollOffsetGeneraterFactory.Instance.GetControlDataRollOffsetGenerater(this.RollSytle,0,0,3,0);
    
                this.UpdateTimer = new Timer();
                this.UpdateTimer.Interval = 500;
                this.UpdateTimer.Enabled = true;
                this.UpdateTimer.Tick += delegate { this.OnTick(); };
            }
    
            #region 辅助
    
            /// <summary>
            /// 定时器
            /// </summary>
            private Timer UpdateTimer;
    
            /// <summary>
            /// 笔刷
            /// </summary>
            SolidBrush Brush;
    
            /// <summary>
            /// 用于显示内容的矩形
            /// </summary>
            Rectangle StringRect = Rectangle.Empty;
    
            /// <summary>
            /// 滚动的偏移量生成器
            /// </summary>
            IControlDataRollOffsetGenerater ControlDataRollOffsetGenerater;
    
            /// <summary>
            /// 图形
            /// </summary>
            Graphics Graphics;
    
            #endregion
    
            #region 数据
    
            /// <summary>
            /// 显示内容
            /// </summary>
            private string _Text;
    
            /// <summary>
            /// 滚动距离
            /// </summary>
            private int _RollDistance = 0;
    
            /// <summary>
            /// 控件内容的滚动样式
            /// </summary>
            private EnumTextRollStyle _RollStyle = EnumTextRollStyle.TurnLeft;
    
            /// <summary>
            /// 文本宽度
            /// </summary>
            private int _TextWidth;
    
            #endregion
    
            #region 属性
    
            /// <summary>
            /// 文本内容
            /// </summary>
            public override string Text
            {
                get
                {
                    if (DesignMode)
                    {
                        return _Text;
                    }
                    else
                    {
                        return string.Empty;
                    }
                }
                set
                {
                    if (_Text == value) return;
                    _Text = value;
    
                    if (!DesignMode)
                    {
                        if (Graphics != null) TextWidth = (int)(Graphics.MeasureString(value, this.Font).Width);
                        this.Invalidate();
                    }
                }
            }
    
            /// <summary>
            /// 文本宽度
            /// </summary>
            public int TextWidth
            {
                get { return _TextWidth; }
                set
                {
                    if (_TextWidth == value) return;
                    _TextWidth = value;
                    if (ControlDataRollOffsetGenerater != null) ControlDataRollOffsetGenerater.DataWidth = value;
                }
            }
    
            /// <summary>
            /// 前景色
            /// </summary>
            public override Color ForeColor
            {
                get
                {
                    return base.ForeColor;
                }
                set
                {
                    Brush = new SolidBrush(base.ForeColor);
                    base.ForeColor = value;
    
                    //this.Invalidate();
                }
            }
    
            /// <summary>
            /// 控件大小
            /// </summary>
            public override Size Size
            {
                get
                {
                    return base.Size;
                }
                set
                {
                    if (this.Size == value) return;
                    base.Size = value;
                    StringRect.Height = Size.Height - Padding.Top - Padding.Bottom;
                    if (ControlDataRollOffsetGenerater != null) ControlDataRollOffsetGenerater.WindowWidth = this.Size.Width - Padding.Left - Padding.Right;
                }
            }
    
            /// <summary>
            /// 内部间距
            /// </summary>
            public override Padding Padding
            {
                get
                {
                    return base.Padding;
                }
                set
                {
                    if (value == Padding) return;
                    base.Padding = value;
                    StringRect.Y = Padding.Top;
                    StringRect.Height = Size.Height - Padding.Top - Padding.Bottom;
                    if (ControlDataRollOffsetGenerater != null) ControlDataRollOffsetGenerater.WindowWidth = this.Size.Width - Padding.Left - Padding.Right;
                }
            }
    
            /// <summary>
            /// 滚动速度
            /// </summary>
            public int RedrawTimeSpan
            {
                get { return UpdateTimer.Interval; }
                set
                {
                    UpdateTimer.Interval = value;
                }
            }
    
            /// <summary>
            /// 滚动速度:每次刷新文本显示位置的间距
            /// </summary>
            public int RoolSpeed
            {
                get
                {
                    return ControlDataRollOffsetGenerater.Speed;
                }
                set
                {
                    ControlDataRollOffsetGenerater.Speed = value;
                }
            }
    
            /// <summary>
            /// 当前显示位置与初始位置的距离
            /// </summary>
            public int RollDistance
            {
                get { return _RollDistance; }
                set { _RollDistance = value; }
            }
    
            /// <summary>
            /// 控件内容的滚动样式
            /// </summary>
            public EnumTextRollStyle RollSytle
            {
                get { return _RollStyle; }
                set
                {
                    if (_RollStyle == value) return;
                    _RollStyle = value;
                    ControlDataRollOffsetGenerater = ControlDataRollOffsetGeneraterFactory.Instance.GetControlDataRollOffsetGenerater(value, StringRect.Width, TextWidth, this.RedrawTimeSpan, this.RollDistance);
                }
            }
    
            #endregion
    
            private void OnTick()
            {
                //if (ControlDataRollOffsetGenerater == null) return;
    
                RollDistance = ControlDataRollOffsetGenerater.GetNextOffset();
                StringRect.X = this.Padding.Left + RollDistance;
    
                StringRect.Width = ControlDataRollOffsetGenerater.WindowWidth - RollDistance;
    
                this.Invalidate();
            }
    
            protected override void OnPaint(PaintEventArgs e)
            {
                if (Graphics == null)
                {
                    Graphics = e.Graphics;
                    TextWidth = (int)(Graphics.MeasureString(_Text, this.Font).Width);
                }
    
                e.Graphics.DrawString(_Text, this.Font, Brush, StringRect);
    
                base.OnPaint(e);
            }
        }
    
        /// <summary>
        /// 控件文本内容滚动的样式
        /// </summary>
        public enum EnumTextRollStyle
        {
            /// <summary>
            /// 向左滚动
            /// </summary>
            TurnLeft,
    
            /// <summary>
            /// 向左滚动
            /// </summary>
            TurnRight,
    
            /// <summary>
            /// 来回滚动
            /// </summary>
            PingPong
        }
    
        public class ControlDataRollOffsetGeneraterFactory
        {
            #region 单例
    
            static Singleton<ControlDataRollOffsetGeneraterFactory> Singleton;
    
            public static ControlDataRollOffsetGeneraterFactory Instance
            {
                get
                {
                    if (Singleton == null) Singleton = new Singleton<ControlDataRollOffsetGeneraterFactory>();
                    return Singleton.Instance;
                }
            }
    
            #endregion
    
            /// <summary>
            /// 获取一个数据滚动的偏移量生成器
            /// </summary>
            /// <param name="RollStyle"></param>
            /// <param name="WindowWidth"></param>
            /// <param name="DataWidth"></param>
            /// <param name="Speed"></param>
            /// <param name="InitOffset"></param>
            /// <returns></returns>
            public IControlDataRollOffsetGenerater GetControlDataRollOffsetGenerater(EnumTextRollStyle RollStyle, int WindowWidth, int DataWidth, int Speed, int InitOffset)
            {
                switch (RollStyle)
                {
                    case EnumTextRollStyle.TurnLeft:
                        return new ControlDataRollToLeftOffsetGenerater(WindowWidth, DataWidth, Speed, InitOffset);
                }
    
                return null;
            }
        }
    
        /// <summary>
        /// 控件内容滚动偏移量生成器的接口
        /// </summary>
        public interface IControlDataRollOffsetGenerater
        {
            /// <summary>
            /// 显示区域宽度
            /// </summary>
            int WindowWidth { get;set;}
    
            /// <summary>
            /// 数据宽度
            /// </summary>
            int DataWidth { get;set;}
    
            /// <summary>
            /// 偏移量
            /// </summary>
            int Offset { get;set;}
    
            /// <summary>
            /// 移动速度
            /// </summary>
            int Speed { get;set;}
    
            /// <summary>
            /// 获取下一个偏移量
            /// </summary>
            /// <returns>新偏移量</returns>
            int GetNextOffset();
        }
    
        /// <summary>
        /// 控件内容滚动偏移量生成器基类
        /// </summary>
        public class ControlDataRollOffsetGeneraterBase : IControlDataRollOffsetGenerater
        {
            public ControlDataRollOffsetGeneraterBase()
            {
    
            }
    
            public ControlDataRollOffsetGeneraterBase(int WindowWidth, int DataWidth, int Speed)
            {
                this._WindowWidth = WindowWidth;
                this._DataWidth = DataWidth;
                this._Speed = Speed;
            }
    
            public ControlDataRollOffsetGeneraterBase(int WindowWidth, int DataWidth, int Speed, int InitOffset)
            {
                this._WindowWidth = WindowWidth;
                this._DataWidth = DataWidth;
                this._Speed = Speed;
                this._Offset = InitOffset;
            }
    
            #region 数据
    
            /// <summary>
            /// 显示区域宽度
            /// </summary>
            int _WindowWidth;
    
            /// <summary>
            /// 数据宽度
            /// </summary>
            int _DataWidth;
    
            /// <summary>
            /// 偏移量
            /// </summary>
            int _Offset;
    
            /// <summary>
            /// 移动速度
            /// </summary>
            int _Speed;
    
            #endregion
    
            #region 属性
    
            /// <summary>
            /// 显示区域宽度
            /// </summary>
            public virtual int WindowWidth
            {
                get
                {
                    return _WindowWidth;
                }
                set
                {
                    _WindowWidth = value;
                }
            }
    
            /// <summary>
            /// 数据宽度
            /// </summary>
            public virtual int DataWidth
            {
                get
                {
                    return _DataWidth;
                }
                set
                {
                    _DataWidth = value;
                }
            }
    
            /// <summary>
            /// 偏移量
            /// </summary>
            public virtual int Offset
            {
                get
                {
                    return _Offset;
                }
                set
                {
                    _Offset = value;
                }
            }
    
            /// <summary>
            /// 移动速度
            /// </summary>
            public virtual int Speed
            {
                get
                {
                    return _Speed;
                }
                set
                {
                    _Speed = value;
                }
            }
    
            #endregion
    
            /// <summary>
            /// 获取下一个偏移量
            /// </summary>
            /// <returns>新偏移量</returns>
            public virtual int GetNextOffset()
            {
                return 0;
            }
        }
    
        /// <summary>
        /// 控件内容向左滚动的偏移量生成器
        /// </summary>
        public class ControlDataRollToLeftOffsetGenerater : ControlDataRollOffsetGeneraterBase
        {
            public ControlDataRollToLeftOffsetGenerater(int WindowWidth, int DataWidth, int Speed)
                : base(WindowWidth, DataWidth, Speed)
            {
                //RollWidth = WindowWidth + DataWidth;
            }
    
            public ControlDataRollToLeftOffsetGenerater(int WindowWidth, int DataWidth, int Speed, int InitOffset)
                : base(WindowWidth, DataWidth, Speed)
            {
                //RollWidth = WindowWidth + DataWidth;
            }
    
            #region 数据
    
            //private int _RollWidth;
    
            #endregion
    
            #region 属性
    
            public override int WindowWidth
            {
                get
                {
                    return base.WindowWidth;
                }
                set
                {
                    base.WindowWidth = value;
                    //RollWidth = DataWidth + WindowWidth;
                }
            }
    
            public override int DataWidth
            {
                get
                {
                    return base.DataWidth;
                }
                set
                {
                    base.DataWidth = value;
                    //RollWidth = DataWidth + WindowWidth;
                }
            }
    
            //public int RollWidth
            //{
            //    get
            //    {
            //        return _RollWidth;
            //    }
            //    set
            //    {
            //        if (value < 0) _RollWidth = 0;
            //    }
            //}
    
            #endregion
    
            /// <summary>
            /// 获取一个新的偏移量
            /// </summary>
            /// <returns></returns>
            public override int GetNextOffset()
            {
                if (Offset < -DataWidth)
                {
                    Offset = WindowWidth;
                }
                else
                {
                    Offset -= Speed;
                }
    
                return Offset;
            }
        }
    }
  • 相关阅读:
    将requirejs进行到底(一)
    localStorage.ie6.js
    再见,唐家岭!
    彻底理解JavaScript原型
    总结javascript继承的两种方式的N中写法
    Sizzle引擎执行的流程图
    武功唯快不破
    密码强度
    各大浏览器内核(Rendering Engine)
    Angularjs中编写指令模版
  • 原文地址:https://www.cnblogs.com/yedaoq/p/1711945.html
Copyright © 2011-2022 走看看