文本跑马灯特效控件----------WinForm控件开发系列
Posted tlmbem
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了文本跑马灯特效控件----------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; [Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))] public override Color BackColor get return base.BackColor; set base.BackColor = value; protected override Size DefaultSize get return new Size(300, 60); /// <summary> /// 文本选项轮播的时间间隔累计(-1为动画正在切换中)(-2出现后停留中) /// </summary> private int intervalTimeValue = 0; /// <summary> /// 文本选项播放时间间隔定时器 /// </summary> private Timer intervalTimer; /// <summary> /// 文本选项出现后停留时间累计 /// </summary> private int remainTimeValue = 0; /// <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); #region 重写 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]; #region Scroll 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(); #endregion #region Speed SpeedSpringback 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]; RectangleF text_lgb_rectf = new RectangleF(textItem.current_char_rectf[0].X, textItem.current_char_rectf[0].Y, textItem.current_char_rectf[textItem.TextChar.Length - 1].Right, textItem.current_char_rectf[0].Height); LinearGradientBrush text_lgb = new LinearGradientBrush(text_lgb_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.TextChar[k], textItem.TextFont, text_lgb, textItem.current_char_rectf[k]); text_lgb.Dispose(); #endregion protected override void OnResize(EventArgs e) base.OnResize(e); this.InitializeTextRectangles(); #endregion #region 动画 /// <summary> /// 动画开始事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void intervalTimer_Tick(object sender, EventArgs e) #region 第一步检查动画是否为进行中 if (this.intervalTimeValue == -1)//动画进行中 return; #endregion #region 第二步检查文本是否为动画完成后停留中 if (this.intervalTimeValue == -2)//停留中 this.remainTimeValue += this.intervalTimer.Interval; if (this.remainTimeValue < this.Items[this.CurrentIndex].RemainTime * 1000) return; this.remainTimeValue = 0; this.intervalTimeValue = 0; #endregion #region 第三步检查是否要进行重复播放 if (this.CurrentIndex > -1) this.Items[this.CurrentIndex].CurrentRepetition += 1; if (this.Items[this.CurrentIndex].CurrentRepetition <= this.Items[this.CurrentIndex].Repetition) goto DH; else this.Items[this.CurrentIndex].CurrentRepetition = 0; #endregion #region 第四步检查下一个文本选项是否禁用,禁用则跳到下下一个文本选项 int index = this.CurrentIndex + 1; if (index > this.Items.Count - 1) index -= this.Items.Count; if (!this.Items[index].Enabled) this.CurrentIndex++; if (this.CurrentIndex > this.Items.Count - 1) this.CurrentIndex -= this.Items.Count; #endregion #region 第五步检查是否是时间进入下一个文本选项动画播放 this.intervalTimeValue += this.intervalTimer.Interval; if (this.intervalTimeValue < this.IntervalTime) return; this.intervalTimeValue = -1; this.CurrentIndex++; if (this.CurrentIndex > this.Items.Count - 1) this.CurrentIndex -= this.Items.Count; #endregion #region 播放动画 DH: 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 = 100f * (textItem.Orientation == AnimationOrientation.Right ? (float)textItem.prev_rectf.Width : (float)textItem.prev_rectf.Height);//动画时间由文字长度决定,速度为每个像素使用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); #endregion /// <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 = textItem.prev_char_rectf[i].X; float y = textItem.prev_char_rectf[i].Y; if (textItem.Orientation == AnimationOrientation.Top || textItem.Orientation == AnimationOrientation.Bottom) y = textItem.prev_char_rectf[i].Y + (float)((textItem.target_char_rectf[i].Y - textItem.prev_char_rectf[i].Y) * e.progressTime); else if (textItem.Orientation == AnimationOrientation.Right) x = textItem.prev_char_rectf[i].X + (float)((textItem.target_char_rectf[i].X - textItem.prev_char_rectf[i].X) * e.progressTime); textItem.current_char_rectf[i] = new RectangleF(x, 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 = textItem.prev_char_rectf[i].X; float y = textItem.prev_char_rectf[i].Y; if (textItem.Orientation == AnimationOrientation.Top || textItem.Orientation == AnimationOrientation.Bottom) y = textItem.prev_char_rectf[i].Y + (float)((textItem.target_char_rectf[i].Y - textItem.prev_char_rectf[i].Y) * e.progressTime); else if (textItem.Orientation == AnimationOrientation.Right) x = textItem.prev_char_rectf[i].X + (float)((textItem.target_char_rectf[i].X - textItem.prev_char_rectf[i].X) * e.progressTime); textItem.current_char_rectf[i] = new RectangleF(x, 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 = -2; #endregion #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; #region Scroll 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; if (textItem.TextCenter) 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; if (textItem.TextCenter) 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); #endregion #region Speed 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]; textItem.target_char_rectf = new RectangleF[len]; for (int i = 0; i < len; i++) float x = 0; float y = 0; float target_x = 0; float target_y = 0; if (textItem.Orientation == AnimationOrientation.Top) float tmp_x = rect.X + i * avg_w; x = tmp_x; if (textItem.TextCenter) x = tmp_x + (rect.Width - text_size.Width) / 2; if (x < tmp_x) x = tmp_x; y = rect.Y - i * text_size.Height; target_x = x; target_y = (rect.Height - text_size.Height) / 2; else if (textItem.Orientation == AnimationOrientation.Bottom) float tmp_x = rect.X + i * avg_w; x = tmp_x; if (textItem.TextCenter) x = tmp_x + (rect.Width - text_size.Width) / 2; if (x < tmp_x) x = tmp_x; y = rect.Bottom + i * text_size.Height; target_x = x; target_y = (rect.Height - text_size.Height) / 2; else if (textItem.Orientation == AnimationOrientation.Right) x = rect.Right + i * rect.Width; y = (rect.Height - text_size.Height) / 2; target_x = rect.X + i * avg_w; target_y = y; textItem.TextChar[i] = textItem.Text.Substring(i, 1); textItem.prev_char_rectf[i] = new RectangleF(x, y, avg_w, text_size.Height); textItem.current_char_rectf[i] = textItem.prev_char_rectf[i]; textItem.target_char_rectf[i] = new RectangleF(target_x, target_y, avg_w, text_size.Height); #endregion #region SpeedSpringback 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]; textItem.target_char_rectf = new RectangleF[len]; for (int i = 0; i < len; i++) float x = 0; float y = 0; float target_x = 0; float target_y = 0; if (textItem.Orientation == AnimationOrientation.Top) float tmp_x = rect.X + i * avg_w; x = tmp_x; if (textItem.TextCenter) x = tmp_x + (rect.Width - text_size.Width) / 2; if (x < tmp_x) x = tmp_x; y = rect.Y - text_size.Height - text_size.Height - text_size.Height / 2; target_x = x; target_y = (rect.Height - text_size.Height) / 2; else if (textItem.Orientation == AnimationOrientation.Bottom) float tmp_x = rect.X + i * avg_w; x = tmp_x; if (textItem.TextCenter) x = tmp_x + (rect.Width - text_size.Width) / 2; if (x < tmp_x) x = tmp_x; y = rect.Bottom + text_size.Height + text_size.Height / 2; target_x = x; target_y = (rect.Height - text_size.Height) / 2; else if (textItem.Orientation == AnimationOrientation.Right) x = rect.Right + i * avg_w * 3; y = (rect.Height - text_size.Height) / 2; target_x = rect.X + i * avg_w; target_y = y; textItem.TextChar[i] = textItem.Text.Substring(i, 1); textItem.prev_char_rectf[i] = new RectangleF(x, y, avg_w, text_size.Height); textItem.current_char_rectf[i] = textItem.prev_char_rectf[i]; textItem.target_char_rectf[i] = new RectangleF(target_x, target_y, avg_w, text_size.Height); #endregion #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 bool enabled = true; /// <summary> /// 文本选项是否参与轮播 /// </summary> [DefaultValue(true)] [Description("文本选项是否参与轮播")] public bool Enabled get return this.enabled; set if (this.enabled == value) return; this.enabled = value; 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 int remainTime = 0; /// <summary> /// 文本选项出现后停留时间(默认0秒) /// </summary> [DefaultValue(0)] [Description("文本选项出现后停留时间(默认0秒)")] public int RemainTime get return this.remainTime; set if (this.remainTime == value || value < 0) return; this.remainTime = value; private int repetition = 1; /// <summary> /// 文本选项在单次循环轮播中重复次数(默认1次) /// </summary> [DefaultValue(1)] [Description("文本选项在单次循环轮播中重复次数(默认1次)")] public int Repetition get return this.repetition; set if (this.repetition == value || value < 1) return; this.repetition = 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 bool textCenter = false; /// <summary> /// 文本是否水平居中(仅限垂直动画) /// </summary> [DefaultValue(false)] [Description("文本是否水平居中(仅限垂直动画)")] public bool TextCenter get return this.textCenter; set this.textCenter = 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; private int currentRepetition = 0; /// <summary> /// 文本选项在单次循环轮播中当前的重复次数 /// </summary> [Browsable(false)] [DefaultValue(0)] [Description("文本选项在单次循环轮播中当前的重复次数")] public int CurrentRepetition get return this.currentRepetition; set if (this.currentRepetition == value) return; this.currentRepetition = 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控件开发系列的主要内容,如果未能解决你的问题,请参考以下文章