文本跑马灯特效控件----------WinForm控件开发系列

文本跑马灯特效控件----------WinForm控件开发系列

  /// <summary>
  /// 文本跑马灯特效控件
  /// </summary>
  [ToolboxItem(true)]
  [DefaultProperty("Items")]
  [Description("文本跑马灯特效控件")]
  public partial class TextCarouselExt : Control
  {
    public delegate void IndexEventHandler(object sender, IndexEventArgs e);

    #region

    private event IndexEventHandler indexChanged;
    /// <summary>
    /// 当前正在播放文本选项索引更改事件
    /// </summary>
    [Description("当前正在播放文本选项索引更改事件")]
    public event IndexEventHandler IndexChanged
    {
      add { this.indexChanged += value; }
      remove { this.indexChanged -= value; }
    }

    private bool active = false;
    /// <summary>
    /// 文本轮播激活状态
    /// </summary>
    [DefaultValue(false)]
    [Description("文本轮播激活状态")]
    public bool Active
    {
      get { return this.active; }
      set
      {
        if (this.active == value)
          return;
        this.active = value;
        this.intervalTimer.Enabled = value;
      }
    }

    private int intervalTime = 100;
    /// <summary>
    /// 文本选项轮播的时间间隔
    /// </summary>
    [DefaultValue(100)]
    [Description("文本选项轮播的时间间隔(默认100毫秒)")]
    public int IntervalTime
    {
      get { return this.intervalTime; }
      set
      {
        if (this.intervalTime == value)
          return;
        this.intervalTime = value;
      }
    }

    int currentIndex = -1;
    /// <summary>
    ///当前正在播放文本选项索引 
    /// </summary>
    [Browsable(false)]
    [DefaultValue(-1)]
    [Description("当前正在播放文本选项索引")]
    public int CurrentIndex
    {
      get { return this.currentIndex; }
      set
      {
        if (this.currentIndex == value)
          return;
        this.currentIndex = value;
        if (this.indexChanged != null)
          this.indexChanged(this, new IndexEventArgs() { Index = this.currentIndex, Item = this.Items[this.currentIndex] });
      }
    }

    private TextItemCollection textItemCollection;
    /// <summary>
    /// 文本选项集合
    /// </summary>
    [DefaultValue(null)]
    [Description("文本选项集合")]
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public TextItemCollection Items
    {
      get
      {
        if (this.textItemCollection == null)
          this.textItemCollection = new TextItemCollection(this);
        return this.textItemCollection;
      }
    }

    protected override Size DefaultSize
    {
      get
      {
        return new Size(300, 60);
      }
    }

    /// <summary>
    /// 文本选项轮播的时间间隔累计(-1为动画正在切换中)
    /// </summary>
    private int intervalTimeValue = 0;
    /// <summary>
    /// 文本选项播放时间间隔定时器
    /// </summary>
    private Timer intervalTimer;

    /// <summary>
    /// 动画播放定时器
    /// </summary>
    private AnimationTimer animationTimer;

    #endregion

    public TextCarouselExt()
    {
      SetStyle(ControlStyles.UserPaint, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle(ControlStyles.ResizeRedraw, true);
      SetStyle(ControlStyles.SupportsTransparentBackColor, true);

      InitializeComponent();

      this.InitializeTextRectangles();

      this.intervalTimer = new Timer();
      this.intervalTimer.Interval = 50;
      this.intervalTimer.Tick += new EventHandler(this.intervalTimer_Tick);

      this.animationTimer = new AnimationTimer(this, new AnimationOptions());
      this.animationTimer.AnimationIng += new AnimationTimer.AnimationHandel(this.animationTimer_AnimationIng);
      this.animationTimer.AnimationEnding += new AnimationTimer.AnimationHandel(this.animationTimer_AnimationEnding);

    }

    /// <summary>
    /// 动画开始事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void intervalTimer_Tick(object sender, EventArgs e)
    {
      if (this.intervalTimeValue == -1)//动画进行中
        return;
      this.intervalTimeValue += this.intervalTimer.Interval;
      if (this.intervalTimeValue >= this.IntervalTime)
      {
        this.intervalTimeValue = -1;

        this.CurrentIndex++;
        if (this.CurrentIndex > this.Items.Count - 1)
        {
          this.CurrentIndex -= this.Items.Count;
        }

        TextItem textItem = this.Items[this.CurrentIndex];
        this.animationTimer.Options.Data = textItem;

        if (textItem.Way == AnimationWay.Scroll)
        {
          this.animationTimer.AT = AnimationType.UniformMotion;
          this.animationTimer.Options.Power = 3;
          this.animationTimer.Options.AllTime = 25f * (float)textItem.prev_rectf.Width;//动画时间由文字长度决定,速度为每个像素使用50毫秒
        }
        else if (textItem.Way == AnimationWay.Speed)
        {
          this.animationTimer.AT = AnimationType.EaseOut;
          this.animationTimer.Options.AllTime = textItem.TextChar.Length * 100;
          this.animationTimer.Options.AllTime = 1000d;
        }
        else if (textItem.Way == AnimationWay.SpeedSpringback)
        {
          this.animationTimer.AT = AnimationType.BackOut;
          this.animationTimer.Options.Power = 1;
          this.animationTimer.Options.AllTime = 1000d;
        }

        this.animationTimer.Start(true, 0);
      }
    }

    /// <summary>
    /// 动画进行中事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void animationTimer_AnimationIng(object sender, AnimationEventArgs e)
    {
      TextItem textItem = (TextItem)e.Data;

      if (textItem.Way == AnimationWay.Scroll)
      {
        float x = textItem.prev_rectf.X;
        float y = textItem.prev_rectf.Y;
        if (textItem.Orientation == AnimationOrientation.Top || textItem.Orientation == AnimationOrientation.Bottom)
        {
          y = textItem.prev_rectf.Y + (float)((textItem.target_rectf.Y - textItem.prev_rectf.Y) * e.progressTime);
        }
        else if ( textItem.Orientation == AnimationOrientation.Right)
        {
          x = textItem.prev_rectf.X + (float)((textItem.target_rectf.X - textItem.prev_rectf.X) * e.progressTime);
        }
        textItem.current_rectf = new RectangleF(x, y, textItem.prev_rectf.Width, textItem.prev_rectf.Height);
      }
      else if (textItem.Way == AnimationWay.Speed)
      {
        for (int i = 0; i < textItem.TextChar.Length; i++)
        {
          float x = (float)(textItem.prev_char_rectf[i].X - (textItem.prev_char_rectf[i].X - (this.ClientRectangle.X + i * textItem.TextCharAvgWidth)) * e.progressTime);
          textItem.current_char_rectf[i] = new RectangleF(x, textItem.prev_char_rectf[i].Y, textItem.prev_char_rectf[i].Width, textItem.prev_char_rectf[i].Height);
        }
      }
      else if (textItem.Way == AnimationWay.SpeedSpringback)
      {
        for (int i = 0; i < textItem.TextChar.Length; i++)
        {
          float x = (float)(textItem.prev_char_rectf[i].X - ((textItem.prev_char_rectf[i].X - (this.ClientRectangle.X + i * textItem.TextCharAvgWidth))) * e.progressTime);
          textItem.current_char_rectf[i] = new RectangleF(x, textItem.prev_char_rectf[i].Y, textItem.prev_char_rectf[i].Width, textItem.prev_char_rectf[i].Height);
        }
      }

      this.Invalidate();
    }

    /// <summary>
    /// 动画结束时事件
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void animationTimer_AnimationEnding(object sender, AnimationEventArgs e)
    {
      this.intervalTimeValue = 0;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);

      if (this.Items.Count < 0 || this.CurrentIndex < 0)
        return;
      Graphics g = e.Graphics;
      TextItem textItem = this.Items[this.CurrentIndex];

      if (textItem.Way == AnimationWay.Scroll)
      {
        if (textItem.TextColorItems.Count < 1)
        {
          SolidBrush text_sb = new SolidBrush(textItem.TextColor);
          g.DrawString(textItem.Text, textItem.TextFont, text_sb, textItem.current_rectf);
          text_sb.Dispose();
        }
        else
        {
          int len = Math.Max(textItem.TextColorItems.Count, 2);
          Color[] colors = new Color[len];
          float[] interval = new float[len];

          for (int i = 0; i < textItem.TextColorItems.Count; i++)
          {
            colors[i] = textItem.TextColorItems[i].ShadeColor;
            interval[i] = textItem.TextColorItems[i].Shade;
          }
          if (textItem.TextColorItems.Count == 1)
          {
            colors[1] = textItem.TextColorItems[0].ShadeColor;
            interval[1] = textItem.TextColorItems[0].Shade;
          }
          //Positions开始值必须为0,结束值必须为1
          interval[0] = 0.0f;
          interval[textItem.TextColorItems.Count - 1] = 1.0f;

          LinearGradientBrush text_lgb = new LinearGradientBrush(textItem.current_rectf, Color.Transparent, Color.Transparent, textItem.ShadeAngle);
          text_lgb.InterpolationColors = new ColorBlend() { Colors = colors, Positions = interval };
          g.DrawString(textItem.Text, textItem.TextFont, text_lgb, textItem.current_rectf);
          text_lgb.Dispose();
        }
      }
      else if (textItem.Way == AnimationWay.Speed || textItem.Way == AnimationWay.SpeedSpringback)
      {
        if (textItem.TextColorItems.Count < 1)
        {
          SolidBrush text_sb = new SolidBrush(textItem.TextColor);
          for (int i = 0; i < textItem.TextChar.Length; i++)
          {
            g.DrawString(textItem.TextChar[i], textItem.TextFont, text_sb, textItem.current_char_rectf[i]);
          }
          text_sb.Dispose();
        }
        else
        {
          int len = Math.Max(textItem.TextColorItems.Count, 2);
          Color[] colors = new Color[len];
          float[] interval = new float[len];
          LinearGradientBrush text_lgb = new LinearGradientBrush(textItem.current_rectf, Color.Transparent, Color.Transparent, textItem.ShadeAngle);

          for (int k = 0; k < textItem.TextChar.Length; k++)
          {
            for (int i = 0; i < textItem.TextColorItems.Count; i++)
            {
              colors[i] = textItem.TextColorItems[i].ShadeColor;
              interval[i] = textItem.TextColorItems[i].Shade;
            }
            if (textItem.TextColorItems.Count == 1)
            {
              colors[1] = textItem.TextColorItems[0].ShadeColor;
              interval[1] = textItem.TextColorItems[0].Shade;
            }
            //Positions开始值必须为0,结束值必须为1
            interval[0] = 0.0f;
            interval[textItem.TextColorItems.Count - 1] = 1.0f;
            text_lgb.InterpolationColors = new ColorBlend() { Colors = colors, Positions = interval };

            g.DrawString(textItem.Text.Substring(k, 1), textItem.TextFont, text_lgb, textItem.current_char_rectf[k]);
          }
          text_lgb.Dispose();
        }

      }
    }

    protected override void OnResize(EventArgs e)
    {
      base.OnResize(e);

      this.InitializeTextRectangles();
    }

    #region

    /// <summary>
    /// 初始化播放前每一段文本rect
    /// </summary>
    private void InitializeTextRectangles()
    {
      for (int i = 0; i < this.Items.Count; i++)
      {
        this.InitializeTextRectangle(this.Items[i]);
      }
    }

    /// <summary>
    /// 初始化文本rect
    /// </summary>
    /// <param name="textItem"></param>
    private void InitializeTextRectangle(TextItem textItem)
    {
      Rectangle rect = this.ClientRectangle;
      Size text_size = TextRenderer.MeasureText(textItem.Text, textItem.TextFont, new Size(), TextFormatFlags.ExternalLeading);
      int len = textItem.Text.Length;
      int avg_w = len == 0 ? 0 : text_size.Width / len;

      if (textItem.Way == AnimationWay.Scroll)
      {
        float x = 0;
        float y = 0;
        float target_x = 0;
        float target_y = 0;
        if (textItem.Orientation == AnimationOrientation.Top)
        {
          x = rect.X + (rect.Width - text_size.Width) / 2;
          if (x < rect.X)
            x = rect.X;
          y = rect.Y - text_size.Height;

          target_x = x;
          target_y = rect.Bottom + text_size.Height;
        }
        else if (textItem.Orientation == AnimationOrientation.Bottom)
        {
          x = rect.X + (rect.Width - text_size.Width) / 2;
          if (x < rect.X)
            x = rect.X;
          y = rect.Bottom;

          target_x = x;
          target_y = rect.Y - text_size.Height;
        }
        else if (textItem.Orientation == AnimationOrientation.Right)
        {
          x = rect.Right;
          y = (rect.Height - text_size.Height) / 2;

          target_x = rect.X - text_size.Width;
          target_y = y;
        }
        textItem.prev_rectf = new RectangleF(x, y, text_size.Width, text_size.Height);
        textItem.current_rectf = textItem.prev_rectf;

        textItem.target_rectf = new RectangleF(target_x, target_y, text_size.Width, text_size.Height);

      }
      else if (textItem.Way == AnimationWay.Speed)
      {
        textItem.TextCharAvgWidth = text_size.Width / len;

        textItem.TextChar = new string[len];
        textItem.prev_char_rectf = new RectangleF[len];
        textItem.current_char_rectf = new RectangleF[len];
        for (int i = 0; i < len; i++)
        {
          textItem.TextChar[i] = textItem.Text.Substring(i, 1);
          textItem.prev_char_rectf[i] = new RectangleF(rect.Right + i * rect.Width, (rect.Height - text_size.Height) / 2, avg_w, text_size.Height);
          textItem.current_char_rectf[i] = textItem.prev_char_rectf[i];
        }
      }
      else if (textItem.Way == AnimationWay.SpeedSpringback)
      {
        textItem.TextCharAvgWidth = text_size.Width / len;

        textItem.TextChar = new string[len];
        textItem.prev_char_rectf = new RectangleF[len];
        textItem.current_char_rectf = new RectangleF[len];
        for (int i = 0; i < len; i++)
        {
          textItem.TextChar[i] = textItem.Text.Substring(i, 1);
          textItem.prev_char_rectf[i] = new RectangleF(rect.Right + i * avg_w * 3, (rect.Height - text_size.Height) / 2, avg_w, text_size.Height);
          textItem.current_char_rectf[i] = textItem.prev_char_rectf[i];
        }
      }
    }

    #endregion

    protected override void Dispose(bool disposing)
    {
      if (disposing && (components != null))
      {
        components.Dispose();
        if (this.intervalTimer != null)
        {
          this.intervalTimer.Dispose();
        }
        if (this.animationTimer != null)
        {
          this.animationTimer.Dispose();
        }
      }
      base.Dispose(disposing);
    }

    /// <summary>
    /// 文本选项集合
    /// </summary>
    [Description("文本选项集合")]
    [Editor(typeof(CollectionEditorExt), typeof(UITypeEditor))]
    public sealed class TextItemCollection : IList, ICollection, IEnumerable
    {
      private ArrayList textItemList = new ArrayList();
      private TextCarouselExt owner;

      public TextItemCollection(TextCarouselExt owner)
      {
        this.owner = owner;
      }

      #region IEnumerable

      public IEnumerator GetEnumerator()
      {
        TextItem[] listArray = new TextItem[this.textItemList.Count];
        for (int index = 0; index < listArray.Length; ++index)
          listArray[index] = (TextItem)this.textItemList[index];
        return listArray.GetEnumerator();
      }

      #endregion

      #region ICollection

      public void CopyTo(Array array, int index)
      {
        for (int i = 0; i < this.Count; i++)
          array.SetValue(this.textItemList[i], i + index);
      }

      public int Count
      {
        get
        {
          return this.textItemList.Count;
        }
      }

      public bool IsSynchronized
      {
        get
        {
          return false;
        }
      }

      public object SyncRoot
      {
        get
        {
          return (object)this;
        }
      }

      #endregion

      #region IList

      public int Add(object value)
      {
        TextItem textItem = (TextItem)value;
        this.textItemList.Add(textItem);
        this.owner.InitializeTextRectangle(textItem);
        this.owner.Invalidate();
        return this.Count - 1;
      }

      public void Clear()
      {
        this.textItemList.Clear();
        this.owner.Invalidate();
      }

      public bool Contains(object value)
      {
        return this.IndexOf(value) != -1;
      }

      public int IndexOf(object value)
      {
        return this.textItemList.IndexOf(value);
      }

      public void Insert(int index, object value)
      {
        throw new NotImplementedException();
      }

      public bool IsFixedSize
      {
        get { return false; }
      }

      public bool IsReadOnly
      {
        get { return false; }
      }

      public void Remove(object value)
      {
        if (!(value is TextItem))
          return;
        this.textItemList.Remove((TextItem)value);
        this.owner.Invalidate();
      }

      public void RemoveAt(int index)
      {
        this.textItemList.RemoveAt(index);
        this.owner.Invalidate();
      }

      public TextItem this[int index]
      {
        get
        {
          return (TextItem)this.textItemList[index];
        }
        set
        {
          this.textItemList[index] = (TextItem)value;
          this.owner.InitializeTextRectangle((TextItem)value);
          this.owner.Invalidate();
        }
      }

      object IList.this[int index]
      {
        get
        {
          return (object)this.textItemList[index];
        }
        set
        {
          this.textItemList[index] = (TextItem)value;
          this.owner.InitializeTextRectangle((TextItem)value);
          this.owner.Invalidate();
        }
      }

      #endregion

    }

    /// <summary>
    /// 渐变颜色选项集合
    /// </summary>
    [Description("渐变颜色选项集合")]
    [Editor(typeof(CollectionEditorExt), typeof(UITypeEditor))]
    public sealed class ShadeColorItemCollection : IList, ICollection, IEnumerable
    {
      private ArrayList shadeColorItemList = new ArrayList();

      public ShadeColorItemCollection()
      {

      }

      #region IEnumerable

      public IEnumerator GetEnumerator()
      {
        ShadeColorItem[] listArray = new ShadeColorItem[this.shadeColorItemList.Count];
        for (int index = 0; index < listArray.Length; ++index)
          listArray[index] = (ShadeColorItem)this.shadeColorItemList[index];
        return listArray.GetEnumerator();
      }

      #endregion

      #region ICollection

      public void CopyTo(Array array, int index)
      {
        for (int i = 0; i < this.Count; i++)
          array.SetValue(this.shadeColorItemList[i], i + index);
      }

      public int Count
      {
        get
        {
          return this.shadeColorItemList.Count;
        }
      }

      public bool IsSynchronized
      {
        get
        {
          return false;
        }
      }

      public object SyncRoot
      {
        get
        {
          return (object)this;
        }
      }

      #endregion

      #region IList

      public int Add(object value)
      {
        ShadeColorItem textItem = (ShadeColorItem)value;
        this.shadeColorItemList.Add(textItem);
        return this.Count - 1;
      }

      public void Clear()
      {
        this.shadeColorItemList.Clear();
      }

      public bool Contains(object value)
      {
        return this.IndexOf(value) != -1;
      }

      public int IndexOf(object value)
      {
        return this.shadeColorItemList.IndexOf(value);
      }

      public void Insert(int index, object value)
      {
        throw new NotImplementedException();
      }

      public bool IsFixedSize
      {
        get { return false; }
      }

      public bool IsReadOnly
      {
        get { return false; }
      }

      public void Remove(object value)
      {
        if (!(value is ShadeColorItem))
          return;
        this.shadeColorItemList.Remove((ShadeColorItem)value);
      }

      public void RemoveAt(int index)
      {
        this.shadeColorItemList.RemoveAt(index);
      }

      public ShadeColorItem this[int index]
      {
        get
        {
          return (ShadeColorItem)this.shadeColorItemList[index];
        }
        set
        {
          this.shadeColorItemList[index] = (ShadeColorItem)value;
        }
      }

      object IList.this[int index]
      {
        get
        {
          return (object)this.shadeColorItemList[index];
        }
        set
        {
          this.shadeColorItemList[index] = (ShadeColorItem)value;
        }
      }

      #endregion

    }

    /// <summary>
    /// 文本选项
    /// </summary>
    [Description("文本选项")]
    public class TextItem
    {

      private AnimationWay way = AnimationWay.Scroll;
      /// <summary>
      /// 动画方式
      /// </summary>
      [DefaultValue(AnimationWay.Scroll)]
      [Description("动画方式")]
      public AnimationWay Way
      {
        get { return this.way; }
        set
        {
          if (this.way == value)
            return;
          this.way = value;
        }
      }

      private AnimationOrientation orientation = AnimationOrientation.Right;
      /// <summary>
      /// 动画出现方向
      /// </summary>
      [DefaultValue(AnimationOrientation.Right)]
      [Description("动画方式")]
      public AnimationOrientation Orientation
      {
        get { return this.orientation; }
        set
        {
          if (this.orientation == value)
            return;
          this.orientation = value;
        }
      }

      private string text = "";
      /// <summary>
      /// 文本
      /// </summary>
      [DefaultValue("")]
      [Description("文本字体")]
      public string Text
      {
        get { return this.text; }
        set
        {
          if (this.text == value)
            return;
          this.text = value;
        }
      }

      private string[] textChar = null;
      /// <summary>
      /// 文本每个字符集合
      [Browsable(false)]
      [DefaultValue(null)]
      [Description("文本每个字符集合")]
      public string[] TextChar
      {
        get { return this.textChar; }
        set
        {
          this.textChar = value;
        }
      }

      private float textCharAvgWidth = 0f;
      /// <summary>
      /// 文本每个字符平均宽度
      [Browsable(false)]
      [DefaultValue(0f)]
      [Description("文本每个字符平均宽度")]
      public float TextCharAvgWidth
      {
        get { return this.textCharAvgWidth; }
        set
        {
          this.textCharAvgWidth = value;
        }
      }

      private Font textFont = new Font("宋体", 20);
      /// <summary>
      /// 文本字体
      /// </summary>
      [DefaultValue(typeof(Font), "宋体, 20pt")]
      [Description("文本字体")]
      public Font TextFont
      {
        get { return this.textFont; }
        set
        {
          if (this.textFont == value)
            return;
          this.textFont = value;
        }
      }

      private Color textColor = Color.FromArgb(154, 205, 50);
      /// <summary>
      /// 文本颜色
      /// </summary>
      [DefaultValue(typeof(Color), "154, 205, 50")]
      [Description("文本颜色")]
      [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
      public Color TextColor
      {
        get { return this.textColor; }
        set
        {
          if (this.textColor == value)
            return;
          this.textColor = value;
        }
      }

      private ShadeColorItemCollection shadeColorItemCollection;
      /// <summary>
      /// 渐变颜色选项集合
      /// </summary>
      [DefaultValue(null)]
      [Description("渐变颜色选项集合")]
      [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
      public ShadeColorItemCollection TextColorItems
      {
        get
        {
          if (this.shadeColorItemCollection == null)
            this.shadeColorItemCollection = new ShadeColorItemCollection();
          return this.shadeColorItemCollection;
        }
      }

      private float shadeAngle = 0f;
      /// <summary>
      /// 渐变方向线的角度(从 X 轴以顺时针角度计算)
      /// </summary>
      [DefaultValue(0f)]
      [Description("渐变方向线的角度(从 X 轴以顺时针角度计算)")]
      public float ShadeAngle
      {
        get { return this.shadeAngle; }
        set
        {
          if (this.shadeAngle == value || value < 0f || value > 360f)
            return;
          this.shadeAngle = value;
        }
      }

      /// <summary>
      /// 运动前rectf
      /// </summary>
      [Browsable(false)]
      [Description("运动前rectf")]
      public RectangleF prev_rectf { get; set; }

      /// <summary>
      /// 目标rectf
      /// </summary>
      [Browsable(false)]
      [Description("目标rectf")]
      public RectangleF target_rectf { get; set; }

      /// <summary>
      /// 当前rectf
      /// </summary>
      [Browsable(false)]
      [Description("当前rectf")]
      public RectangleF current_rectf { get; set; }

      /// <summary>
      /// 运动前每个字的rectf
      /// </summary>
      [Browsable(false)]
      [Description("运动前rectf")]
      public RectangleF[] prev_char_rectf { get; set; }

      /// <summary>
      /// 目标每个字rectf
      /// </summary>
      [Browsable(false)]
      [Description("目标每个字rectf")]
      public RectangleF target_char_rectf { get; set; }

      /// <summary>
      /// 当前每个字的rectf
      /// </summary>
      [Browsable(false)]
      [Description("当前rectf")]
      public RectangleF[] current_char_rectf { get; set; }
    }

    /// <summary>
    /// 渐变颜色选项
    /// </summary>
    [Description("渐变颜色选项")]
    public class ShadeColorItem
    {

      private float shade = 0f;
      /// <summary>
      /// 渐变值0-1
      /// </summary>
      [DefaultValue(0f)]
      [Description("渐变值0-1")]
      public float Shade
      {
        get { return this.shade; }
        set
        {
          if (this.shade == value || value < 0 || value > 1)
            return;
          this.shade = value;
        }
      }

      private Color shadeColor = Color.Empty;
      /// <summary>
      /// 渐变值对应渐变颜色
      /// </summary>
      [DefaultValue(typeof(Color), "Empty")]
      [Description("渐变值对应渐变颜色")]
      [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]
      public Color ShadeColor
      {
        get { return this.shadeColor; }
        set
        {
          if (this.shadeColor == value)
            return;
          this.shadeColor = value;
        }
      }

    }

    /// <summary>
    /// 动画方式
    /// </summary>
    [Description("动画方式")]
    public enum AnimationWay
    {
      /// <summary>
      /// 普通滚动
      /// </summary>
      Scroll,
      /// <summary>
      /// 减速
      /// </summary>
      Speed,
      /// <summary>
      /// 减速回弹
      /// </summary>
      SpeedSpringback
    }

    /// <summary>
    /// 动画出现方向
    /// </summary>
    [Description("控件滑块方向位置")]
    public enum AnimationOrientation
    {
      /// <summary>
      ///从上边出现
      /// </summary>
      Top,
      /// <summary>
      /// 从下边出现
      /// </summary>
      Bottom,
      /// <summary>
      /// 从右边出现
      /// </summary>
      Right
    }

    /// <summary>
    /// 当前正在播放文本选项索引更改事件参数
    /// </summary>
    [Description("当前正在播放文本选项索引更改事件参数")]
    public class IndexEventArgs : EventArgs
    {
      /// <summary>
      /// 当前正在播放文本选项索引
      /// </summary>
      [Description("当前正在播放文本选项索引")]
      public float Index { get; set; }

      /// <summary>
      /// 当前正在播放文本选项
      /// </summary>
      [Description("当前正在播放文本选项")]
      public TextItem Item { get; set; }
    }

  }

源码下载:文本跑马灯特效控件.zip

文本跑马灯特效控件----------WinForm控件开发系列

上一篇:Web服务器管理系列:5、利用MSConfig排查木马


下一篇:rabbitMq API