WindowsForm滑块控件

public class ZhmSlider : Control
    {
        private Rectangle foreRect;
        private Rectangle backRect;
        private Rectangle setRect;

        private Color backgroundColor = Color.White;
        private Color foregroundColor = Color.Gray;
        private Color setRectColor = Color.Black;//滑块颜色
        private Color fontColor = Color.Black;
        private Color borderColor = Color.Black;

        private int maximum = 100; //进度条最大值
        private int minimum = 0;  //进度条最小值
        private double _value = 0;//进度条当前值

        private bool showPercent; //当前进度百分比
        private float fontSize = 9;// 
        private FontFamily _fontFamily = new FontFamily("Segoe UI");

        private Point originPoint;
        private Point originsetRectPoint;
        private bool setRectDown = false;

        public ZhmSlider()
        {
            // 避免重绘时窗口闪烁
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);

            this.MouseDown += ZhmSlider_MouseDown;
            this.MouseMove += ZhmSlider_MouseMove;
            this.MouseUp += ZhmSlider_MouseUp;
        }

        private void ZhmSlider_MouseUp(object sender, MouseEventArgs e)
        {
            setRectDown = false;
        }

        private void ZhmSlider_MouseMove(object sender, MouseEventArgs e)
        {
            if (setRectDown)
            {
                int dd = e.Location.X - originPoint.X;

                double percent = (double)(originsetRectPoint.X + dd - this.backRect.X) / (this.backRect.Width - this.backRect.Height);
                if (percent < 0)
                {
                    this.Value = minimum;
                    this.foreRect.Width = 0;
                    this.setRect.X = backRect.X;
                }
                else if (percent > 1)
                {
                    this.Value = maximum;
                    this.foreRect.Width = this.backRect.Width;
                    this.setRect.X = backRect.X + backRect.Width - backRect.Height;
                }
                else
                {
                    this.Value = percent * maximum;
                    this.foreRect.Width = (int)(percent * this.backRect.Width);
                    this.setRect.X = originsetRectPoint.X + dd;
                }
                Invalidate();
            }
        }

        private void ZhmSlider_MouseDown(object sender, MouseEventArgs e)
        {
            if (setRect.Contains(e.Location))
            {
                this.originPoint = e.Location;
                originsetRectPoint = this.setRect.Location;
                this.setRectDown = true;
            }
        }

        [Category("扩展属性"), Browsable(true)]
        public bool ShowPercentTag
        {
            get { return showPercent; }
            set
            {
                showPercent = value;
                Invalidate();
            }
        }
        [Category("扩展属性"),  Browsable(true)]
        public int Maximum
        {
            get { return maximum; }
            set
            {
                maximum = value;
                Invalidate();
            }
        }
        [Category("扩展属性"),  Browsable(true)]
        public int Minimum
        {
            get { return minimum; }
            set
            {
                minimum = value;
                Invalidate();
            }
        }

        [Category("扩展属性"), Browsable(true)]
        public float FontSize
        {
            get { return fontSize; }
            set
            {
                this.fontSize = value;
                Invalidate();
            }
        }
        [Category("扩展属性"), Browsable(true)]
        public FontFamily FontFamily
        {
            get { return _fontFamily; }
            set
            {
                this._fontFamily = value;
                Invalidate();
            }
        }

        [Category("扩展属性"), Browsable(true)]
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set
            {
                this.backgroundColor = value;
                Invalidate();
            }
        }
        [Category("扩展属性"), Browsable(true)]
        public Color ForegroundColor
        {
            get { return foregroundColor; }
            set
            {
                this.foregroundColor = value;
                Invalidate();
            }
        }
        [Category("扩展属性"), Browsable(true)]
        public Color SetRectColor
        {
            get { return setRectColor; }
            set
            {
                this.setRectColor = value;
                Invalidate();
            }
        }
        [Category("扩展属性"), Browsable(true)]
        public Color FontColor
        {
            get { return fontColor; }
            set
            {
                this.fontColor = value;
                Invalidate();
            }
        }

        [Category("扩展属性"), Browsable(true)]
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                this.borderColor = value;
                Invalidate();
            }
        }


        //确定控件的位置。 我们根据宽度和高度属性确定矩形的位置。 因为Control类也有这两个属性,所以我们在前面添加new来覆盖原来的属性 
        [Category("扩展属性"), Browsable(true)]
        public new int Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                foreRect.X = backRect.X = base.Width / 20;
                backRect.Width = base.Width * 9 / 10;
                foreRect.Width = (int)(_value / maximum * backRect.Width);
                setRect.X = (int)(_value / maximum * (backRect.Width - backRect.Height) + foreRect.X);

                Invalidate();
            }
        }
        [Category("扩展属性"), Browsable(true)]
        public new int Height
        {
            get { return base.Height; }
            set
            {
                base.Height = value;
                foreRect.Height = backRect.Height = setRect.Height = setRect.Width = base.Height / 3;
                foreRect.Y = backRect.Y = setRect.Y = base.Height / 3;
                Invalidate();
            }
        }

        //值发生变化的属性。 当向事件添加外部响应函数时,事件将生效,否则OnValueChanged方法的值为空 
        protected EventHandler OnValueChanged;
        public event EventHandler ValueChanged
        {
            add
            {
                if (OnValueChanged != null)
                    foreach (Delegate d in OnValueChanged.GetInvocationList())
                        if (object.ReferenceEquals(d, value)) return;
                OnValueChanged = (EventHandler)Delegate.Combine(OnValueChanged, value);
            }
            remove
            {
                OnValueChanged = (EventHandler)Delegate.Remove(OnValueChanged, value);
            }
        }

        //定义value的值。 当Value值发生变化时,重置矩形的进度,控制块的位置,并重新绘制控件(如果在value属性中修改进度条的值,请使用_value变量,在其他地方,请使Value属性 )
        [Category("扩展属性"), Browsable(true)]
        public double Value
        {
            get { return _value; }
            set
            {
                if (_value < Minimum)
                    throw new ArgumentException("Less than minimum");
                if (_value > Maximum)
                    throw new ArgumentException("Exceeds the maximum");

                _value = value;
                foreRect.Width = (int)(_value / maximum * backRect.Width);
                setRect.X = (int)(_value / maximum * (backRect.Width - backRect.Height) + backRect.X);

                if ((_value - maximum) > 0)
                {
                    foreRect.Width = backRect.Width;
                    setRect.X = backRect.Width - backRect.Height + backRect.X;
                }

                if (OnValueChanged != null)
                    OnValueChanged(this, EventArgs.Empty);

                Invalidate();
            }
        }
        //绘制控件,重载OnPaint方法来绘制控件 
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            DrawRect(pe.Graphics);
            DrawText(pe.Graphics);
        }

        //滑块区域
        private void DrawRect(Graphics e)
        {
            Pen pen = new Pen(this.foregroundColor);

            e.FillRectangle(new SolidBrush(this.backgroundColor), backRect);
            e.DrawRectangle(new Pen(this.borderColor), backRect);

            e.FillRectangle(new SolidBrush(this.foregroundColor), foreRect);
            e.DrawRectangle(new Pen(this.borderColor), foreRect);

            e.FillRectangle(new SolidBrush(this.setRectColor), setRect);
            e.DrawRectangle(new Pen(this.borderColor), setRect);
        }

         // 绘制文本
        private void DrawText(Graphics e)
        {
            Point point = new Point();
            point.X = this.backRect.X + this.backRect.Width * 3 / 7;
            point.Y = this.backRect.Y + this.backRect.Height / 3;

            SolidBrush brush = new SolidBrush(fontColor);
            Font font = new Font(_fontFamily, this.fontSize);
            string percent = ((int)this._value).ToString() + "%";

            //设置文本居中
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            e.DrawString(percent, font, brush, backRect, format);
        }

        //在设计期间更改控件的大小时调用OnResize方法。 当您拖动边缘上的箭头来更改控件的大小时,当需要对控件进行相应更改时,可以重写此方法。如果没有重新加载,则只有在修改完成后才会更新控件。
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Width = Width;
            this.Height = Height;
            Invalidate();
        }
    }
posted @ 2022-06-13 11:20  壮哈苗  阅读(626)  评论(1编辑  收藏  举报