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;
        }
    }
}

转载于:https://www.cnblogs.com/yedaoq/archive/2010/04/14/1711945.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值