/// <summary>/// 多点滑块进度控件/// </summary>[ToolboxItem(true)][DefaultProperty("Items")][DefaultEvent("SlideValueChanged")][Description("多点滑块进度控件")]public partial class SlideBarExt : Control{public delegate void EventHandler(object sender, SlideValueEventArgs e);#regionprivate event EventHandler slideValueChanged;/// <summary>/// 滑块选项值更改事件/// </summary>[Description("滑块选项值更改事件")]public event EventHandler SlideValueChanged{add { this.slideValueChanged += value; }remove { this.slideValueChanged -= value; }}private SlideOrientation orientation = SlideOrientation.HorizontalBottom;/// <summary>/// 控件滑块方向位置/// </summary>
    [DefaultValue(SlideOrientation.HorizontalBottom)][Description("控件滑块方向位置")]public SlideOrientation Orientation{get { return this.orientation; }set{if (this.orientation == value)return;this.orientation = value;this.InitializeSlideValueRectangleFs();this.Invalidate();}}private int slidePadding = 6;/// <summary>/// 控件边距/// </summary>[DefaultValue(6)][Description("控件边距")]public int SlidePadding{get { return this.slidePadding; }set{if (this.slidePadding == value || value < 0)return;this.slidePadding = value;this.InitializeSlideValueRectangleFs();this.Invalidate();}}private float maxValue = 100f;/// <summary>/// 最大值/// </summary>
    [DefaultValue(100f)][Description("最大值")]public float MaxValue{get { return this.maxValue; }set{if (this.maxValue == value || value < this.minValue)return;this.maxValue = value;this.Invalidate();}}private float minValue = 0f;/// <summary>/// 最小值/// </summary>
    [DefaultValue(0f)][Description("最小值")]public float MinValue{get { return this.minValue; }set{if (this.minValue == value || value > this.maxValue)return;this.minValue = value;this.Invalidate();}}#region 背景private Color backdropColor = Color.FromArgb(76, 240, 128, 128);/// <summary>/// 背景颜色/// </summary>[DefaultValue(typeof(Color), "76, 240, 128, 128")][Description("背景颜色")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color BackdropColor{get { return this.backdropColor; }set{if (this.backdropColor == value)return;this.backdropColor = value;this.Invalidate();}}private int backdropThickness = 8;/// <summary>/// 背景大小/// </summary>[DefaultValue(8)][Description("背景大小")]public int BackdropThickness{get { return this.backdropThickness; }set{if (this.backdropThickness == value || value < 0)return;this.backdropThickness = value;this.Invalidate();}}private bool backdropRadius = true;/// <summary>/// 背景是否为圆角/// </summary>[DefaultValue(true)][Description("背景是否为圆角")]public bool BackdropRadius{get { return this.backdropRadius; }set{if (this.backdropRadius == value)return;this.backdropRadius = value;this.Invalidate();}}#endregion#region 滑块private int slideWidth = 20;/// <summary>/// 滑块宽度/// </summary>[DefaultValue(20)][Description("滑块宽度")]public int SlideWidth{get { return this.slideWidth; }set{if (this.slideWidth == value || value < 0)return;this.slideWidth = value;this.InitializeSlideValueRectangleFs();this.Invalidate();}}private int slideHeight = 20;/// <summary>/// 滑块高度/// </summary>[DefaultValue(20)][Description("滑块高度")]public int SlideHeight{get { return this.slideHeight; }set{if (this.slideHeight == value || value < 0)return;this.slideHeight = value;this.InitializeSlideValueRectangleFs();this.Invalidate();}}private int slideRadius = 10;/// <summary>/// 滑块圆角大小(限于Flat)/// </summary>[DefaultValue(10)][Description("滑块圆角大小(限于Flat)")]public int SlideRadius{get { return this.slideRadius; }set{if (this.slideRadius == value || value < 0)return;this.slideRadius = value;this.InitializeSlideValueRectangleFs();this.Invalidate();}}private Color slideColor = Color.FromArgb(255, 128, 128);/// <summary>/// 滑块颜色(总体设置)/// </summary>[DefaultValue(typeof(Color), "255, 128, 128")][Description("滑块颜色(总体设置)")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color SlideColor{get { return this.slideColor; }set{if (this.slideColor == value)return;this.slideColor = value;this.Invalidate();}}private Color slideProgressColor = Color.FromArgb(175, 240, 128, 128);/// <summary>/// 滑块进度颜色(仅限于只有一个滑块)/// </summary>[DefaultValue(typeof(Color), "175, 240, 128, 128")][Description("滑块进度颜色(仅限于只有一个滑块)")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color SlideProgressColor{get { return this.slideProgressColor; }set{if (this.slideProgressColor == value)return;this.slideProgressColor = value;this.Invalidate();}}private int selectIndex = -1;/// <summary>/// 当前选中滑块的索引/// </summary>[Browsable(false)][DefaultValue(-1)][Description("当前选中滑块的索引")]public int SelectIndex{get { return this.selectIndex; }}private SlideValueCollection slideValueCollection;/// <summary>/// 滑块选项集合/// </summary>[DefaultValue(null)][Description("滑块选项集合")][DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]public SlideValueCollection Items{get{if (this.slideValueCollection == null)this.slideValueCollection = new SlideValueCollection(this);return this.slideValueCollection;}}#endregion#region 提示信息private bool tipShow = true;/// <summary>/// 是否显示提示信息/// </summary>[DefaultValue(true)][Description("是否显示提示信息")]public bool TipShow{get { return this.tipShow; }set{if (this.tipShow == value)return;this.tipShow = value;this.Invalidate();}}private Color tipBackdropColor = Color.FromArgb(126, 255, 128, 128);/// <summary>/// 提示信息背景颜色/// </summary>[DefaultValue(typeof(Color), "126, 255, 128, 128")][Description("提示信息背景颜色")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color TipBackdropColor{get { return this.tipBackdropColor; }set{if (this.tipBackdropColor == value)return;this.tipBackdropColor = value;this.Invalidate();}}private Font tipFont = new Font("宋体", 11, FontStyle.Regular);/// <summary>/// 提示信息字体/// </summary>[DefaultValue(typeof(Font), "11pt style=Regular")][Description("提示信息字体")]public Font TipFont{get { return this.tipFont; }set{if (this.tipFont == value)return;this.tipFont = value;this.Invalidate();}}private Color tipColor = Color.FromArgb(150, 255, 255, 255);/// <summary>/// 提示信息颜色/// </summary>[DefaultValue(typeof(Color), "150,255, 255, 255")][Description("提示信息颜色")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color TipColor{get { return this.tipColor; }set{if (this.tipColor == value)return;this.tipColor = value;this.Invalidate();}}#endregionprotected override Size DefaultSize{get{return new Size(300, 60);}}/// <summary>/// 鼠标状态/// </summary>private MoveStatus move_status = MoveStatus.Leave;/// <summary>/// 鼠标坐标/// </summary>private Point move_point;#endregionpublic SlideBarExt(){SetStyle(ControlStyles.UserPaint, true);SetStyle(ControlStyles.AllPaintingInWmPaint, true);SetStyle(ControlStyles.OptimizedDoubleBuffer, true);SetStyle(ControlStyles.ResizeRedraw, true);SetStyle(ControlStyles.SupportsTransparentBackColor, true);InitializeComponent();}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);Graphics g = e.Graphics;g.SmoothingMode = SmoothingMode.AntiAlias;Rectangle rectf = new Rectangle(this.SlidePadding, this.SlidePadding, e.ClipRectangle.Width - this.SlidePadding * 2, e.ClipRectangle.Height - this.SlidePadding * 2);#region 背景Pen backdrop_pen = new Pen(this.BackdropColor, this.BackdropThickness);int backdrop_x_start = 0;int backdrop_x_end = 0;int backdrop_y = 0;if (this.Orientation == SlideOrientation.HorizontalTop || this.Orientation == SlideOrientation.HorizontalBottom){backdrop_x_start = rectf.X;backdrop_x_end = rectf.Right;backdrop_y = (this.Orientation == SlideOrientation.HorizontalTop) ? this.SlidePadding + this.SlideHeight / 2 : rectf.Bottom - this.SlideHeight / 2 - this.SlidePadding;if (this.BackdropRadius){backdrop_pen.StartCap = LineCap.Round;backdrop_pen.EndCap = LineCap.Round;backdrop_x_start += this.BackdropThickness / 2;backdrop_x_end -= this.BackdropThickness / 2;}g.DrawLine(backdrop_pen, backdrop_x_start, backdrop_y, backdrop_x_end, backdrop_y);}else{backdrop_x_start = rectf.Y;backdrop_x_end = rectf.Bottom;backdrop_y = (this.Orientation == SlideOrientation.VerticalLeft) ? this.SlidePadding + this.SlideWidth / 2 : rectf.Right - this.SlideWidth / 2 - this.SlidePadding;if (this.BackdropRadius){backdrop_pen.StartCap = LineCap.Round;backdrop_pen.EndCap = LineCap.Round;backdrop_x_start += this.BackdropThickness / 2;backdrop_x_end -= this.BackdropThickness / 2;}g.DrawLine(backdrop_pen, backdrop_y, backdrop_x_start, backdrop_y, backdrop_x_end);}backdrop_pen.Dispose();#endregion#region 进度值if (this.Orientation == SlideOrientation.HorizontalTop || this.Orientation == SlideOrientation.HorizontalBottom){if (this.Items.Count == 1){int slideProgress_x_start = rectf.X;int slideProgress_x_end = (int)(this.Items[0].RectF.Right - this.Items[0].RectF.Width) + this.SlideWidth / 2;int slideProgress_y = (this.Orientation == SlideOrientation.HorizontalTop) ? this.SlidePadding + this.SlideHeight / 2 : rectf.Bottom - this.SlideHeight / 2 - this.SlidePadding;Pen slideProgress_pen = new Pen(this.SlideProgressColor, this.BackdropThickness);if (this.BackdropRadius){slideProgress_pen.StartCap = LineCap.Round;slideProgress_x_start += this.BackdropThickness / 2;}g.DrawLine(slideProgress_pen, slideProgress_x_start, slideProgress_y, slideProgress_x_end, slideProgress_y);slideProgress_pen.Dispose();}}else{if (this.Items.Count == 1){int slideProgress_x_start = rectf.Bottom;int slideProgress_x_end = (int)(this.Items[0].RectF.Bottom - this.Items[0].RectF.Height);int slideProgress_y = (this.Orientation == SlideOrientation.VerticalLeft) ? this.SlidePadding + this.SlideWidth / 2 : rectf.Right - this.SlideWidth / 2 - this.SlidePadding;Pen slideProgress_pen = new Pen(this.SlideProgressColor, this.BackdropThickness);if (this.BackdropRadius){slideProgress_pen.StartCap = LineCap.Round;slideProgress_x_start -= this.BackdropThickness / 2;}g.DrawLine(slideProgress_pen, slideProgress_y, slideProgress_x_start, slideProgress_y, slideProgress_x_end);slideProgress_pen.Dispose();}}#endregion#region  滑块int line_area = 6;//连线区域大小Pen tooltipline_pen = new Pen(this.TipBackdropColor, 2);SolidBrush tooltipback_sb = new SolidBrush(this.TipBackdropColor);for (int i = 0; i < this.Items.Count; i++){#region 滑块SolidBrush slide_sb = new SolidBrush(this.Items[i].SlideColor == Color.Empty ? this.SlideColor : this.Items[i].SlideColor);GraphicsPath slide_gp = TransformCircular(new RectangleF(this.Items[i].RectF.X, this.Items[i].RectF.Y, this.Items[i].RectF.Width, this.Items[i].RectF.Height), this.SlideRadius);g.FillPath(slide_sb, slide_gp);slide_gp.Dispose();slide_sb.Dispose();#endregion#region 计算提示信息的位置if (this.TipShow){string tooltiptext_str = this.Items[i].Value.ToString("F2");Size tooltiptext_size = TextRenderer.MeasureText(tooltiptext_str, this.TipFont, new Size(), TextFormatFlags.NoPadding | TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);Rectangle tooltipback_rect = new Rectangle(0, 0, tooltiptext_size.Width, tooltiptext_size.Height);if (this.Orientation == SlideOrientation.HorizontalTop){tooltipback_rect.X = (int)this.Items[i].RectF.X + ((int)this.Items[i].RectF.Width - tooltipback_rect.Width) / 2;if (tooltipback_rect.X < 0)tooltipback_rect.X = 0;tooltipback_rect.Y = (int)this.Items[i].RectF.Bottom + line_area;if (i > 0 && (tooltipback_rect.X < this.Items[i - 1].TipRect.Right + line_area)){tooltipback_rect.X = (int)this.Items[i - 1].TipRect.Right + line_area;}}else if (this.Orientation == SlideOrientation.HorizontalBottom){tooltipback_rect.X = (int)this.Items[i].RectF.X + ((int)this.Items[i].RectF.Width - tooltipback_rect.Width) / 2;if (tooltipback_rect.X < 0)tooltipback_rect.X = 0;tooltipback_rect.Y = (int)this.Items[i].RectF.Y - line_area - tooltipback_rect.Height;if (i > 0 && (tooltipback_rect.X < this.Items[i - 1].TipRect.Right + line_area)){tooltipback_rect.X = (int)this.Items[i - 1].TipRect.Right + line_area;}}else if (this.Orientation == SlideOrientation.VerticalLeft){tooltipback_rect.X = (int)this.Items[i].RectF.Right + line_area;tooltipback_rect.Y = (int)this.Items[i].RectF.Y + ((int)this.Items[i].RectF.Height - tooltipback_rect.Height) / 2;if (tooltipback_rect.Y > rectf.Bottom - tooltipback_rect.Height)tooltipback_rect.Y = rectf.Bottom - tooltipback_rect.Height;if (i > 0 && (tooltipback_rect.Y > (int)this.Items[i - 1].TipRect.Y - line_area - tooltipback_rect.Height)){tooltipback_rect.Y = (int)this.Items[i - 1].TipRect.Y - line_area - tooltipback_rect.Height;}}else if (this.Orientation == SlideOrientation.VerticalRight){tooltipback_rect.X = (int)this.Items[i].RectF.X - line_area - tooltipback_rect.Width;tooltipback_rect.Y = (int)this.Items[i].RectF.Y + ((int)this.Items[i].RectF.Height - tooltipback_rect.Height) / 2;if (tooltipback_rect.Y > rectf.Bottom - tooltipback_rect.Height)tooltipback_rect.Y = rectf.Bottom - tooltipback_rect.Height;if (i > 0 && (tooltipback_rect.Y > (int)this.Items[i - 1].TipRect.Y - line_area - tooltipback_rect.Height)){tooltipback_rect.Y = (int)this.Items[i - 1].TipRect.Y - line_area - tooltipback_rect.Height;}}this.Items[i].TipRect = tooltipback_rect;}#endregion}#regionif (this.TipShow){for (int i = this.Items.Count - 1; i >= 0; i--){if (this.Orientation == SlideOrientation.HorizontalTop || this.Orientation == SlideOrientation.HorizontalBottom){if ((i == this.Items.Count - 1)){if (this.Items[i].TipRect.Right > rectf.Right)this.Items[i].TipRect = new Rectangle((int)(rectf.Right - this.Items[i].TipRect.Width), this.Items[i].TipRect.Y, this.Items[i].TipRect.Width, this.Items[i].TipRect.Height);}else{if (this.Items[i].TipRect.Right + line_area > this.Items[i + 1].TipRect.X)this.Items[i].TipRect = new Rectangle((this.Items[i + 1].TipRect.X - this.Items[i].TipRect.Width - line_area), this.Items[i].TipRect.Y, this.Items[i].TipRect.Width, this.Items[i].TipRect.Height);}this.Items[i].Slidepoint = new PointF(this.Items[i].RectF.X + this.Items[i].RectF.Width / 2, this.Items[i].RectF.Bottom);this.Items[i].Tippoint = new PointF(this.Items[i].TipRect.X + this.Items[i].TipRect.Width / 2, this.Items[i].TipRect.Y);if (this.Orientation == SlideOrientation.HorizontalBottom){this.Items[i].Slidepoint = new PointF(this.Items[i].RectF.X + this.Items[i].RectF.Width / 2, this.Items[i].RectF.Y);this.Items[i].Tippoint = new PointF(this.Items[i].TipRect.X + this.Items[i].TipRect.Width / 2, this.Items[i].TipRect.Bottom);}}else if (this.Orientation == SlideOrientation.VerticalLeft || this.Orientation == SlideOrientation.VerticalRight){if (i == this.Items.Count - 1){if (this.Items[i].TipRect.Y < rectf.Y)this.Items[i].TipRect = new Rectangle(this.Items[i].TipRect.X, rectf.Y, this.Items[i].TipRect.Width, this.Items[i].TipRect.Height);}else{if (this.Items[i].TipRect.Y < this.Items[i + 1].TipRect.Bottom + line_area)this.Items[i].TipRect = new Rectangle(this.Items[i].TipRect.X, this.Items[i + 1].TipRect.Bottom + line_area, this.Items[i].TipRect.Width, this.Items[i].TipRect.Height);}this.Items[i].Slidepoint = new PointF(this.Items[i].RectF.Right, this.Items[i].RectF.Bottom - this.Items[i].RectF.Height / 2);this.Items[i].Tippoint = new PointF(this.Items[i].TipRect.Left, this.Items[i].TipRect.Bottom - this.Items[i].TipRect.Height / 2);if (this.Orientation == SlideOrientation.VerticalRight){this.Items[i].Slidepoint = new PointF(this.Items[i].RectF.X, this.Items[i].RectF.Bottom - this.Items[i].RectF.Height / 2);this.Items[i].Tippoint = new PointF(this.Items[i].TipRect.Right, this.Items[i].TipRect.Bottom - this.Items[i].TipRect.Height / 2);}}g.DrawLine(tooltipline_pen, this.Items[i].Slidepoint, this.Items[i].Tippoint);g.FillRectangle(tooltipback_sb, this.Items[i].TipRect);string tooltiptext_str = this.Items[i].Value.ToString("F2");TextRenderer.DrawText(g, tooltiptext_str, this.TipFont, this.Items[i].TipRect, this.TipColor, TextFormatFlags.NoPadding | TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter);}}#endregiontooltipback_sb.Dispose();tooltipline_pen.Dispose();#endregion}protected override void OnResize(EventArgs e){base.OnResize(e);this.InitializeSlideValueRectangleFs();}protected override void OnMouseDown(MouseEventArgs e){base.OnMouseDown(e);this.move_status = MoveStatus.Down;Point point = this.PointToClient(Control.MousePosition);this.move_point = point;this.selectIndex = this.GetSelectSlideIndex(point);}protected override void OnMouseUp(MouseEventArgs e){base.OnMouseUp(e);this.move_status = MoveStatus.Up;this.selectIndex = -1;}protected override void OnMouseEnter(EventArgs e){base.OnMouseEnter(e);this.move_status = MoveStatus.Enter;}protected override void OnMouseLeave(EventArgs e){base.OnMouseLeave(e);this.move_status = MoveStatus.Leave;this.selectIndex = -1;}protected override void OnMouseMove(MouseEventArgs e){base.OnMouseMove(e);if (this.move_status == MoveStatus.Down){if (this.SelectIndex > -1){this.InitializeSlideValue(this.Items[this.SelectIndex]);}}else{Point point = this.PointToClient(Control.MousePosition);this.Cursor = (this.GetSelectSlideIndex(point) > -1) ? Cursors.Hand : Cursors.Default;}}#region/// <summary>/// 根据当前鼠标坐标计算滑块值/// </summary>/// <param name="item">当前滑块</param>private void InitializeSlideValue(SlideValue item){Rectangle rect = new Rectangle(this.SlidePadding, this.SlidePadding, this.ClientRectangle.Width - this.SlidePadding * 2, this.ClientRectangle.Height - this.SlidePadding * 2);Point point = this.PointToClient(Control.MousePosition);if (this.Orientation == SlideOrientation.HorizontalTop || this.Orientation == SlideOrientation.HorizontalBottom){if (point.X == this.move_point.X)return;int index = this.Items.IndexOf(item);float value_l = Math.Abs(this.MinValue) + Math.Abs(this.MaxValue);//值总长度float back_l = rect.Width - this.SlideWidth - (this.Items.Count - 1) * this.SlideWidth;//背景总长度float increment = value_l / back_l;//一个像素代表曾值量float value = item.Value;value += increment * (point.X - this.move_point.X);this.move_point = point;item.Value = value;}else{if (point.Y == this.move_point.Y)return;int index = this.Items.IndexOf(item);float value_l = Math.Abs(this.MinValue) + Math.Abs(this.MaxValue);//值总长度float back_l = rect.Height - this.SlideHeight - (this.Items.Count - 1) * this.SlideHeight;//背景总长度float increment = value_l / back_l;//一个像素代表曾值量float value = item.Value;value -= increment * (point.Y - this.move_point.Y);this.move_point = point;item.Value = value;}}/// <summary>/// 计算所有滑块rectf/// </summary>/// <param name="item"></param>private void InitializeSlideValueRectangleFs(){for (int i = 0; i < this.Items.Count; i++){this.InitializeSlideValueRectangleF(this.Items[i]);}}/// <summary>/// 计算指定滑块rectf/// </summary>/// <param name="item"></param>private void InitializeSlideValueRectangleF(SlideValue item){Rectangle rect = new Rectangle(this.SlidePadding, this.SlidePadding, this.ClientRectangle.Width - this.SlidePadding * 2, this.ClientRectangle.Height - this.SlidePadding * 2);int index = this.Items.IndexOf(item);if (this.Orientation == SlideOrientation.HorizontalBottom || this.Orientation == SlideOrientation.HorizontalTop){float back_l = rect.Width - this.SlideWidth - (this.Items.Count - 1) * this.SlideWidth;int slide_x = this.SlidePadding + (this.SlideWidth / 2) + (int)(item.Value / (Math.Abs(this.MinValue) + Math.Abs(this.MaxValue)) * back_l);if (slide_x < 0)slide_x = 0;if (slide_x > rect.Right - this.SlideWidth / 2)slide_x = rect.Right - this.SlideWidth / 2;int slide_y = (this.Orientation == SlideOrientation.HorizontalTop) ? rect.Y : rect.Bottom - this.SlideHeight - this.SlidePadding;item.RectF = new RectangleF(slide_x - (this.SlideWidth / 2) + index * this.SlideWidth, slide_y, this.SlideWidth, this.SlideHeight);}else{float back_l = rect.Height - this.SlideHeight - (this.Items.Count - 1) * this.SlideHeight;int slide_y = rect.Bottom - (this.SlideHeight / 2) - (int)(item.Value / (Math.Abs(this.MinValue) + Math.Abs(this.MaxValue)) * back_l);if (slide_y < 0)slide_y = 0;if (slide_y > rect.Bottom - this.SlideHeight / 2)slide_y = rect.Bottom - this.SlideHeight / 2;int slide_x = (this.Orientation == SlideOrientation.VerticalLeft) ? rect.X : rect.Right - this.SlideWidth - this.SlidePadding;item.RectF = new RectangleF(slide_x, slide_y - (this.SlideHeight / 2) - index * this.SlideHeight, this.SlideWidth, this.SlideHeight);}}/// <summary>/// 获取选中滑块索引/// </summary>/// <param name="point">当前鼠标坐标</param>/// <returns></returns>private int GetSelectSlideIndex(Point point){for (int i = 0; i < this.Items.Count; i++){if (this.Items[i].RectF.Contains(point))return i;}return -1;}/// <summary>/// 根据画笔大小转换rectf/// </summary>/// <param name="rectf">要转换的rectf</param>/// <param name="pen">画笔大小大小</param>/// <returns></returns>private static RectangleF TransformRectangleF(RectangleF rectf, int pen){RectangleF result = new RectangleF();result.Width = rectf.Width - (pen < 1 ? 0 : pen);result.Height = rectf.Height - (pen < 1 ? 0 : pen);result.X = rectf.X + (float)(pen / 2);result.Y = rectf.Y + (float)(pen / 2);return result;}/// <summary>/// 转换成圆角/// </summary>/// <param name="rectf">要转换的rectf</param>/// <param name="radius">圆角半径的大小</param>/// <returns></returns>private static GraphicsPath TransformCircular(RectangleF rectf, int radius = 0){return TransformCircular(rectf, radius, radius, radius, radius);}/// <summary>/// 转换成圆角/// </summary>/// <param name="rectf">要转换的rectf</param>/// <param name="leftTopRadius">左上角</param>/// <param name="rightTopRadius">右上角</param>/// <param name="rightBottomRadius">右下角</param>/// <param name="leftBottomRadius">左下角</param>/// <returns></returns>private static GraphicsPath TransformCircular(RectangleF rectf, int leftTopRadius = 0, int rightTopRadius = 0, int rightBottomRadius = 0, int leftBottomRadius = 0){GraphicsPath gp = new GraphicsPath();if (leftTopRadius > 0){RectangleF lefttop_rect = new RectangleF(rectf.X, rectf.Y, leftTopRadius * 2, leftTopRadius * 2);gp.AddArc(lefttop_rect, 180, 90);}else{gp.AddLine(new PointF(rectf.X, rectf.Y), new PointF(rightTopRadius > 0 ? rectf.Right - rightTopRadius * 2 : rectf.Right, rectf.Y));}if (rightTopRadius > 0){RectangleF righttop_rect = new RectangleF(rectf.Right - rightTopRadius * 2, rectf.Y, rightTopRadius * 2, rightTopRadius * 2);gp.AddArc(righttop_rect, 270, 90);}else{gp.AddLine(new PointF(rectf.Right, rectf.Y), new PointF(rectf.Right, rightBottomRadius > 0 ? rectf.Bottom - rightTopRadius * 2 : rectf.Bottom));}if (rightBottomRadius > 0){RectangleF rightbottom_rect = new RectangleF(rectf.Right - rightTopRadius * 2, rectf.Bottom - rightTopRadius * 2, rightBottomRadius * 2, rightBottomRadius * 2);gp.AddArc(rightbottom_rect, 0, 90);}else{gp.AddLine(new PointF(rectf.Right, rectf.Bottom), new PointF(leftBottomRadius > 0 ? leftBottomRadius * 2 : rectf.X, rectf.Bottom));}if (leftBottomRadius > 0){RectangleF rightbottom_rect = new RectangleF(rectf.X, rectf.Bottom - leftBottomRadius * 2, leftBottomRadius * 2, leftBottomRadius * 2);gp.AddArc(rightbottom_rect, 90, 90);}else{gp.AddLine(new PointF(rectf.X, rectf.Bottom), new PointF(rectf.X, leftTopRadius > 0 ? rectf.X + leftTopRadius * 2 : rectf.X));}gp.CloseAllFigures();return gp;}#endregionprotected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}/// <summary>/// 滑块选项集合/// </summary>[Description("滑块选项集合")][Editor(typeof(CollectionEditorExt), typeof(UITypeEditor))]public sealed class SlideValueCollection : IList, ICollection, IEnumerable{private ArrayList slideValueList = new ArrayList();private SlideBarExt owner;public SlideValueCollection(SlideBarExt owner){this.owner = owner;}#region IEnumerablepublic IEnumerator GetEnumerator(){SlideValue[] listArray = new SlideValue[this.slideValueList.Count];for (int index = 0; index < listArray.Length; ++index)listArray[index] = (SlideValue)this.slideValueList[index];return listArray.GetEnumerator();}#endregion#region ICollectionpublic void CopyTo(Array array, int index){for (int i = 0; i < this.Count; i++)array.SetValue(this.slideValueList[i], i + index);}public int Count{get{return this.slideValueList.Count;}}public bool IsSynchronized{get{return false;}}public object SyncRoot{get{return (object)this;}}#endregion#region IListpublic int Add(object value){SlideValue slideValue = (SlideValue)value;slideValue.owner = this.owner;slideValue.self = slideValue;this.slideValueList.Add(slideValue);this.owner.InitializeSlideValueRectangleF(slideValue);this.owner.Invalidate();return this.Count - 1;}public void Clear(){this.slideValueList.Clear();this.owner.Invalidate();}public bool Contains(object value){return this.IndexOf(value) != -1;}public int IndexOf(object value){return this.slideValueList.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 SlideValue))return;this.slideValueList.Remove((SlideValue)value);this.owner.Invalidate();}public void RemoveAt(int index){this.slideValueList.RemoveAt(index);this.owner.Invalidate();}public SlideValue this[int index]{get{return (SlideValue)this.slideValueList[index];}set{this.slideValueList[index] = (SlideValue)value;this.owner.InitializeSlideValueRectangleF((SlideValue)value);this.owner.Invalidate();}}object IList.this[int index]{get{return (object)this.slideValueList[index];}set{this.slideValueList[index] = (SlideValue)value;this.owner.InitializeSlideValueRectangleF((SlideValue)value);this.owner.Invalidate();}}#endregion}/// <summary>/// 滑块选项/// </summary>[Description("滑块选项")]public class SlideValue{public SlideValue(){}public SlideValue(SlideBarExt owner){this.owner = owner;}/// <summary>/// 控件主体/// </summary>public SlideBarExt owner;/// <summary>/// 当前滑块选项/// </summary>public SlideValue self;private RectangleF rectf = new RectangleF();/// <summary>/// 滑块rectf/// </summary>[Browsable(false)][Description("滑块rectf")]public RectangleF RectF{get { return this.rectf; }set{if (this.rectf == value)return;this.rectf = value;}}private Rectangle tiprect = new Rectangle();/// <summary>/// 滑块提示信息rect/// </summary>[Browsable(false)][Description("滑块提示信息rect")]public Rectangle TipRect{get { return this.tiprect; }set{if (this.tiprect == value)return;this.tiprect = value;}}private PointF slidepoint = new Point();/// <summary>/// 连线滑块的坐标/// </summary>[Browsable(false)][Description("连线滑块的坐标")]public PointF Slidepoint{get { return this.slidepoint; }set{if (this.slidepoint == value)return;this.slidepoint = value;}}private PointF tippoint = new Point();/// <summary>/// 连线提示信息的坐标/// </summary>[Browsable(false)][Description("连线提示信息的坐标")]public PointF Tippoint{get { return this.tippoint; }set{if (this.tippoint == value)return;this.tippoint = value;}}private float value { get; set; }/// <summary>/// 滑块值/// </summary>[Browsable(true)][DefaultValue("0f")][Description("滑块值")]public float Value{get { return this.value; }set{if (this.value == value)return;if (this.owner != null){if (value < this.owner.MinValue)value = this.owner.MinValue;if (value > this.owner.MaxValue)value = this.owner.MaxValue;int index = this.owner.Items.IndexOf(self);if (this.owner.Items.Count > 1){if (value > this.value)//往右移动
              {if (index < this.owner.Items.Count - 1){if (value > this.owner.Items[index + 1].Value){value = this.owner.Items[index + 1].Value;}}}else if (value < this.value){if (index > 0){if (value < this.owner.Items[index - 1].Value){value = this.owner.Items[index - 1].Value;}}}}this.value = value;this.owner.InitializeSlideValueRectangleF(self);this.owner.Invalidate();if (this.owner.slideValueChanged != null){this.owner.slideValueChanged(this.owner, new SlideValueEventArgs() { Item = self });}}}}private Color slideColor = Color.Empty;/// <summary>/// 滑块颜色/// </summary>[Browsable(true)][DefaultValue(typeof(Color), "Empty")][Description("滑块颜色")][Editor(typeof(ColorEditorExt), typeof(System.Drawing.Design.UITypeEditor))]public Color SlideColor{get { return this.slideColor; }set{if (this.slideColor == value)return;this.slideColor = value;if (this.owner != null){this.owner.Invalidate();}}}}/// <summary>/// 滑块选项值更改事件参数/// </summary>[Description("滑块选项值更改事件参数")]public class SlideValueEventArgs : EventArgs{/// <summary>/// 滑块选项/// </summary>[Description("滑块选项")]public SlideValue Item { get; set; }}/// <summary>/// 鼠标状态/// </summary>[Description("鼠标状态")]private enum MoveStatus{/// <summary>/// 鼠标进入/// </summary>
      Enter,/// <summary>/// 鼠标离开/// </summary>
      Leave,/// <summary>/// 鼠标按下/// </summary>
      Down,/// <summary>/// 鼠标按下释放/// </summary>
      Up}/// <summary>/// 控件滑块方向位置/// </summary>[Description("控件滑块方向位置")]public enum SlideOrientation{/// <summary>///水平放置靠近上边/// </summary>
      HorizontalTop,/// <summary>/// 水平放置靠近下边/// </summary>
      HorizontalBottom,/// <summary>/// 垂直放置靠近左边/// </summary>
      VerticalLeft,/// <summary>/// 垂直放置靠近右边/// </summary>
      VerticalRight,}}

源码下载:多点滑块进度控件.zip

转载于:https://www.cnblogs.com/tlmbem/p/11410163.html

多点滑块滑杆控件----------WinForm控件开发系列相关推荐

  1. .net控件开发系列

    此系列我将尽我所能写下去吧,跟大家分享学习控件开发.也希望大家对我多提意见,让我们共同进步                              net控件开发系列 1.net组件开发系列(-)之 ...

  2. C# 滑块/滑杆/拖动条控件trackBar

    WindForm中的滑块/滑杆/拖动条控件为trackBar,如下图所示.        需要改变拖动条对应的值.显示样式和设置默认值,按下图设置.

  3. 《Dotnet9》系列-开源C# Winform控件库1《HZHControls》强力推荐

    大家好,我是Dotnet9小编,一个从事dotnet开发8年+的程序员.我最近在写dotnet分享文章,希望能让更多人看到dotnet的发展,了解更多dotnet技术,帮助dotnet程序员应用dot ...

  4. winform控件的学习

    最近要研究winform(2.0)的控件和vc++ 2008的控件,先做的是winform控件. 随便找了个CheckedListBox来看看,本来预计20分钟搞定一个自定义List的绑定,然后捉出勾 ...

  5. 基于C#的GIS开发20210426之类库同名类、制作winform控件、建立控件之间的关联、自己制作控件、自己控件引入项目、显示磁盘文件夹、磁盘文件与picturebox建立关系、图像拉伸

    C#知识点与控件的制作 一.C#中多个类库中有同名类,区分问题 二.制作最简单的winform控件 1.拖动加载 事件代理 筛选器 2.显示属性.事件,及其修改 常见控件属性介绍 窗体常用的方法 常见 ...

  6. (转)WinForm控件使用文章收藏整理完成

    http://home.cnblogs.com/group/topic/29829.html 对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. ...

  7. 异步委托实现多线程winform控件编程

            private void button1_Click(object sender, EventArgs e)         {             ThreadStart ts  ...

  8. C# WinForm控件、自定义控件整理(大全)

    C# WinForm开发系列 - CheckBox/Button/Label/ProgressBar WinForm下CheckedListBox的数据绑定 Winform 下无闪烁走马灯效果实现 c ...

  9. 在WPF中使用WinForm控件方法

    在WPF中使用WinForm控件方法 原文:在WPF中使用WinForm控件方法 1.      首先添加对如下两个dll文件的引用:WindowsFormsIntegration.dll,Syste ...

最新文章

  1. Git中级用户的25个提示
  2. html5显示字幕信息,HTML5 Placeholder实现input背景文字提示效果
  3. windows如何清理无效注册表?如何重装python,如何彻底清理python
  4. python排课问题_排课问题分析
  5. 怎么安装python的包_python下如何安装.whl包?
  6. Ubuntu15.10使用mysql
  7. tar.bz2 解压命令
  8. 微电子 半导体 网址 一览表
  9. Teamviewer远程工具使用
  10. 分水岭算法和距离变换函数
  11. 安装Win10之后如何进入BIOS
  12. Echarts icon图标 默认样式 样式总结
  13. 【C#】System.Linq,万能的查询语句
  14. python实现金字塔图案
  15. 【MySQL】 DATE_FORMAT() 格式化时间
  16. 淘宝/天猫获得淘宝店铺详情 API
  17. .shp文件的存储结构是怎样的?底层读取shapefile文件
  18. Abaqus中实现对N个节点施加不同荷载-以位移为例
  19. JAVA计算机毕业设计中医药院校科研会议系统Mybatis+系统+数据库+调试部署
  20. 微信渠道二维码怎么使用?

热门文章

  1. 物流管理软件市场:未来1-2年40%厂商将被淘汰
  2. zzuli OJ 1016: 银行利率
  3. python使用POP3获取邮件信息
  4. ssh中的密码登录和密钥登录
  5. wxpython制作eml文件阅读器
  6. kinect+openni2+nite2+opencv2.4手势跟踪
  7. activereportsjs无限制部署,activereportsjs3.x版本
  8. 【精确延时函数】IAR(MSP430)中的精确延时函数
  9. unity调用摄像头和闪光灯
  10. 软件模型之业务建模|愿景