• 【Winform-自定义控件】一个自定义的进度条


    0.选择基类

     public class MySlider : Control

    1.设置控件的Style

      在构造函数里添加:

            public MySlider()
            {
                //1.设置控件Style
                this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);
    
                //9.1
            }

    2.定义变量,并对一些变量进行一些默认设置

            //2.定义变量,并对一些变量进行一些默认设置
            Rectangle foreRect;
            Rectangle backRect;
            Rectangle setRect;
    
            Color backgroundColor = Color.White;//背景色
            Color foregroundColor = Color.Gray;//已加载颜色
            Color setRectColor = Color.Black;//控制块
            Color fontColor = Color.Black;//字体颜色
    
            int maximum = 100; //进度条的最大值
            int minimum = 0;  //进度条的最小值
            double myValue = 0;//当前进度值
    
            bool showPercent; //显示当前的百分比
            float fontSize = 9;//控件字体的大小
            FontFamily myFontFamily = new FontFamily("宋体"); //控件的字体

    3.设置属性值

            //3.设置属性值
            [Category("General"), Description("Show Percent Tag"), Browsable(true)]
            public bool ShowPercentTag
            {
                get { return showPercent; }
                set
                {
                    showPercent = value;
                    Invalidate();
                }
            }
            [Category("General"), Description("Control's Maximum"), Browsable(true)]
            public int Maximum
            {
                get { return maximum; }
                set
                {
                    maximum = value;
                    Invalidate();
                }
            }
            [Category("General"), Description("Control's Minimum"), Browsable(true)]
            public int Minimum
            {
                get { return minimum; }
                set
                {
                    minimum = value;
                    Invalidate();
                }
            }
    
            [Category("General"), Description("Control's FontSize"), Browsable(true)]
            public float FontSize
            {
                get { return fontSize; }
                set
                {
                    this.fontSize = value;
                    Invalidate();
                }
            }
            [Category("General"), Description("Control's FontFamily"), Browsable(true)]
            public FontFamily MyFontFamily
            {
                get { return myFontFamily; }
                set
                {
                    this.myFontFamily = value;
                    Invalidate();
                }
            }
    
            [Category("Color"), Browsable(true)]
            public Color BackgroundColor
            {
                get { return backgroundColor; }
                set
                {
                    this.backgroundColor = value;
                    Invalidate();
                }
            }
            [Category("Color"), Browsable(true)]
            public Color ForegroundColor
            {
                get { return foregroundColor; }
                set
                {
                    this.foregroundColor = value;
                    Invalidate();
                }
            }
            [Category("Color"), Browsable(true)]
            public Color SetRectColor
            {
                get { return setRectColor; }
                set
                {
                    this.setRectColor = value;
                    Invalidate();
                }
            }
            [Category("Color"), Browsable(true)]
            public Color FontColor
            {
                get { return fontColor; }
                set
                {
                    this.fontColor = value;
                    Invalidate();
                }
            }

    4.确定控件的位置

    //4.确定控件的位置,我们根据 Width 和 Height 属性来确定矩形的位置,由于Control 类也有这两个属性,我们在前面加上new覆盖掉原有的属性
            [Category("General"), Description("Control's Width"), 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)(myValue / maximum * backRect.Width);
                    setRect.X = (int)(myValue / maximum * (backRect.Width - backRect.Height) + foreRect.X);
    
                    Invalidate();
                }
            }
            [Category("General"), Description("Control's Height"), 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();
                }
            }

    5.Value值变化的属性

    //5.Value值变化的属性。当外部为该事件添加了响应函数时,事件就会生效,否则为OnValueChanged的值为null
            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);
                }
            }

    6.定义value属性值

    //6.定义Value的值。当Value值改变的时候,重新设置矩形的进度,控制块的位置,并且重绘控件
            //注意:Value属性内如果对进度条的值进行修改,使用myValue变量,而在其他地方,则用Value属性
            [Category("General"), Description("Control's Value"), Browsable(true)]
            public double Value
            {
                get { return myValue; }
                set
                {
                    if (myValue < Minimum)
                        throw new ArgumentException("小于最小值");
                    if (myValue > Maximum)
                        throw new ArgumentException("超过最大值");
    
                    myValue = value;
                    foreRect.Width = (int)(myValue / maximum * backRect.Width);
                    setRect.X = (int)(myValue / maximum * (backRect.Width - backRect.Height) + backRect.X);
    
                    if ((myValue - maximum) > 0)
                    {
                        foreRect.Width = backRect.Width;
                        setRect.X = backRect.Width - backRect.Height + backRect.X;
                    }
    
                    //如果添加了响应函数,则执行该函数
                    if (OnValueChanged != null)
                    {
                        OnValueChanged(this, EventArgs.Empty);
                    }
    
                    Invalidate();
                }
            }

    7.绘制控件

            //7.绘制控件,重载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(Color.Black), backRect);
    
                e.FillRectangle(new SolidBrush(this.foregroundColor), foreRect);
                e.DrawRectangle(new Pen(Color.Black), foreRect);
    
                e.FillRectangle(new SolidBrush(this.setRectColor), setRect);
                e.DrawRectangle(new Pen(Color.Black), 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(myFontFamily, this.fontSize);
                string percent = ((int)this.myValue).ToString() + "%";
    
                //通过设置StringFormat可以让文字居中显示
                StringFormat format = new StringFormat();
                format.Alignment = StringAlignment.Center;
                format.LineAlignment = StringAlignment.Center;
    
                e.DrawString(percent, font, brush, backRect, format);
            }

    8.在设计时,修改控件的大小

     //8.最后还有一个方法OnResize,在设计时,修改控件的大小会调用这个方法,比如:拖动边缘的箭头改变控件的大小时,控件也要做相应的改变时,就可以重载该方法,如果没有重载,就只有在修改完成后才更新控件,不懂的可以自己试一下 
            protected override void OnResize(EventArgs e)
            {
                base.OnResize(e);
                this.Width = Width;
                this.Height = Height;
                Invalidate();
            }

    9.1响应鼠标事件

            public MySlider()
            {
                //1.设置控件Style
    
                //9.1.控件绘制完了,却不能操作,还要对控件进行操作
                //通过三个鼠标事件函数,让鼠标可以拖动控制条
                this.MouseDown += MySlider_MouseDown;
                this.MouseMove += MySlider_MouseMove;
                this.MouseUp += MySlider_MouseUp;
            }

    9.2响应鼠标事件

            //9.2.添加三个辅助变量,添加响应函数
            Point originPoint;
            Point originsetRectPoint;
            bool setRectDown = false;
    
            void MySlider_MouseUp(object sender, MouseEventArgs e)
            {
                setRectDown = false;
            }
            void MySlider_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();
                }
            }
            void MySlider_MouseDown(object sender, MouseEventArgs e)
            {
                if (setRect.Contains(e.Location))
                {
                    this.originPoint = e.Location;
                    originsetRectPoint = this.setRect.Location;
                    this.setRectDown = true;
                }
            }
  • 相关阅读:
    使用CAShapeLayer做出圆形的进度条 —— #DF!
    NSDate分类,把系统返回的时间与现在进行比较---秀清
    NSPredicate类,指定过滤器的条件---董鑫
    UITextFIeld的输入格式问题 ----W.P
    AttributeText创建多彩文字Label --- hl
    自定义简单动画
    Swift 学习网址精选 By HL
    【C++服务端技术】移动广播
    【C++服务端技术】定时器
    【面试攻略】C++面试-4399
  • 原文地址:https://www.cnblogs.com/Sukie-s-home/p/6767213.html
Copyright © 2020-2023  润新知