1. 程式人生 > 實用技巧 >C#--自定義控制元件-開發LED指示燈控制元件

C#--自定義控制元件-開發LED指示燈控制元件

以下是學習筆記:

參考:https://www.bilibili.com/video/BV1eQ4y1M7ZY?p=5

效果如下:

思考:實現以上效果要用到哪些屬性

顏色,是否有邊框,外環寬度,是否高亮,中心顏色,是否閃爍,顏色列表,閃爍的頻率

如果是開關,就需要bool型別 True,False顏色

如果是多種狀態,當前值數值型別

常規操作:

一,自定義LED顯示的控制元件

1,新增“使用者控制元件”,命名MyLED

2,編寫使用者控制元件的MyLED的程式碼

    public partial class MyLED : UserControl
    {
        public MyLED()
        {
            
            InitializeComponent();

            #region 【1】設定雙緩衝等屬性

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);

            #endregion

        }

        #region 【2】定義三個欄位

        private Graphics g;
        private Pen p;
        private SolidBrush sb;

        #endregion

        #region 【3】新增一個設定Graphics的方法
        
        private void SetGraphics(Graphics g)
        {
            //設定畫布的屬性
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        }

        #endregion

        #region 【4】根據實際控制元件分析的結果,建立屬性

        private Color ledColor = Color.Green;

        [Category("jason控制元件屬性")]
        [Description("LED指示燈演示")]
        public Color LedColor
        {
            get { return ledColor; }
            set
            {
                ledColor = value;
                this.Invalidate();
            }
        }

        #endregion

        #region 【5】建立重繪的事件

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            g = e.Graphics;//獲取畫布
            SetGraphics(g);//設定畫布

            //情況1:如果寬度大於高度(以高度為準)
            if (this.Width > this.Height)
            {
                sb = new SolidBrush(ledColor);
                Rectangle rec=new Rectangle(1,1,this.Height-2,this.Height-2);//建立矩形
                g.FillEllipse(sb,rec);//畫圓
            }
        }

        #endregion
    }

  

3,重新生成後在工具箱裡面就可以看到MyLED的控制元件了,拖入後可以直接使用

注意:如果只有這個程式碼,那只有寬度大於高度的時候才會畫圓。

根據指示燈的功能需求,最終程式碼如下

    public partial class MyLED : UserControl
    {
        public MyLED()
        {
            
            InitializeComponent();

            #region 【1】設定雙緩衝等屬性

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);

            #endregion

        }

        #region 【2】定義三個欄位

        private Graphics g;
        private Pen p;
        private SolidBrush sb;

        #endregion

        #region 【3】新增一個設定Graphics的方法
        
        private void SetGraphics(Graphics g)
        {
            //設定畫布的屬性
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        }

        #endregion

        #region 【4】根據實際控制元件分析的結果,建立屬性

        private Color ledColor = Color.Green;

        [Category("jason控制元件屬性")]
        [Description("LED指示燈演示")]
        public Color LedColor
        {
            get { return ledColor; }
            set
            {
                ledColor = value;
                this.Invalidate();
            }
        }

        private bool isBorder = true;

        [Category("jason控制元件屬性")]
        [Description("是否有邊框")]
        public bool IsBorder
        {
            get { return isBorder; }
            set
            {
                isBorder = value;
                this.Invalidate();
            }
        }

        private int borderWidth = 5;

        [Category("jason控制元件屬性")]
        [Description("圓環的寬度")]
        public int BorderWidth
        {
            get { return borderWidth; }
            set
            {
                borderWidth = value;
                this.Invalidate();
            }
        }

        private int gapWidth = 5;

        [Category("jason控制元件屬性")]
        [Description("間隙的寬度")]
        public int GapWidth
        {
            get { return gapWidth; }
            set
            {
                gapWidth = value;
                this.Invalidate();
            }
        }

        private bool isHighLight = true;

        [Category("jason控制元件屬性")]
        [Description("是否高亮")]
        public bool IsHighLight
        {
            get { return isHighLight; }
            set
            {
                isHighLight = value;
                this.Invalidate();
            }
        }

        private Color centerColor = Color.White;

        [Category("jason控制元件屬性")]
        [Description("漸變中心的顏色")]
        public Color CenterColor
        {
            get { return centerColor; }
            set
            {
                centerColor = value;
                this.Invalidate();
            }
        }

        #endregion

        #region 【5】建立重繪的事件

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            g = e.Graphics;//獲取畫布
            SetGraphics(g);//設定畫布

            #region 1,畫一個圓

            //if (this.Width > this.Height)//情況1:如果寬度大於高度(以高度為準)
            //{
            //    sb = new SolidBrush(ledColor);
            //    Rectangle rec=new Rectangle(1,1,this.Height-2,this.Height-2);//建立矩形
            //    g.FillEllipse(sb,rec);//畫圓
            //}
            //else//情況2:如果高度大於寬度(以寬度為準)
            //{
            //    sb = new SolidBrush(ledColor);
            //    Rectangle rec = new Rectangle(1, 1, this.Width - 2, this.Width - 2);//建立矩形
            //    g.FillEllipse(sb, rec);//畫圓
            //}

            //優化上面的程式碼
            int LEDWidth = Math.Min(this.Width, this.Height);
            sb = new SolidBrush(ledColor);
            RectangleF rec = new RectangleF(1, 1, LEDWidth - 2, LEDWidth - 2);//建立矩形
            g.FillEllipse(sb, rec);//畫圓

            #endregion

            #region 2,在圓裡面畫一個圓環

            //如果有邊框,那就畫一個圓環
            if (isBorder)//引數這裡用欄位或屬性都可以,如果用屬性,程式要都走一些判斷的程式碼
            {
                p = new Pen(this.BackColor, borderWidth);//使用背景色
                //p = new Pen(Color.Red, borderWidth);
                float x = 1 + gapWidth + borderWidth * 0.5f;
                rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                g.DrawEllipse(p, rec);//畫圓環
            }

            #endregion

            #region 3,漸變色繪製,是否高亮

            if (isHighLight)
            {
                //if (isBorder)
                //{
                //    //先確定路徑
                //    GraphicsPath gp = new GraphicsPath();
                //    //float x = 1 + gapWidth + borderWidth * 0.5f;//如果座標是這個,會有點覆蓋圓環
                //    float x = 1 + gapWidth + borderWidth;
                //    rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                //    gp.AddEllipse(rec);//把矩形新增到路徑

                //    //漸變色畫刷,高亮
                //    PathGradientBrush pgb=new PathGradientBrush(gp);//把路徑傳入

                //    pgb.CenterColor = this.centerColor;

                //    //設定有多少組顏色來漸變
                //    pgb.SurroundColors=new Color[]
                //    {
                //        ledColor
                //    };
                //    g.FillPath(pgb,gp);
                //}
                //else
                //{
                //    //先確定路徑
                //    GraphicsPath gp = new GraphicsPath();
                //    float x = 1 ;
                //    rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                //    gp.AddEllipse(rec);

                //    //漸變色畫刷,高亮
                //    PathGradientBrush pgb = new PathGradientBrush(gp);

                //    pgb.CenterColor = this.centerColor;

                //    pgb.SurroundColors = new Color[]
                //    {
                //        ledColor
                //    };
                //    g.FillPath(pgb, gp);
                //}


                //優化上面的if else程式碼
                GraphicsPath gp = new GraphicsPath();
                float x = isBorder? 1 + gapWidth + borderWidth:1;//使用三元運算來判斷,優化程式碼
                rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                gp.AddEllipse(rec);//把矩形新增到路徑

                //漸變色畫刷,高亮
                PathGradientBrush pgb = new PathGradientBrush(gp);//把路徑傳入

                pgb.CenterColor = this.centerColor;

                //設定有多少組顏色來漸變
                pgb.SurroundColors = new Color[]
                {
                        ledColor
                };
                g.FillPath(pgb, gp);
            }

            #endregion


        }

        #endregion
    }

圓的繪製的座標說明:

圓環的繪製的座標說明:

二,在專案中使用自定義控制元件

1,拖入MyLED控制元件

2,在主程式中根據狀態,來改變MyLED控制元件的顏色

            bool myLEDStatus = true;
            this.myLED1.LedColor = myLEDStatus ? Color.LimeGreen : Color.Red;

  

上面用法比較通用,用起來麻煩,如果專案中只是true或false,對自定義控制元件進行改造

三,針對上述呼叫問題進行改造

1,增加三個屬性

        private Color ledTrueColor = Color.Green;

        [Category("jason控制元件屬性")]
        [Description("TRUE的時候LED指示燈顏色")]
        public Color LedTrueColor
        {
            get { return ledTrueColor; }
            set
            {
                ledTrueColor = value;
                this.Invalidate();
            }
        }

        private Color ledFalseColor = Color.Red;

        [Category("jason控制元件屬性")]
        [Description("False的時候LED指示燈顏色")]
        public Color LedFalseColor
        {
            get { return ledFalseColor; }
            set
            {
                ledFalseColor = value;
                this.Invalidate();
            }
        }

        private bool ledStatus = true;

        [Category("jason控制元件屬性")]
        [Description("當前的狀態")]
        public bool LedStatus
        {
            get { return ledStatus; }
            set
            {
                ledStatus = value;
                this.Invalidate();
            }
        }

  

2,把根據狀態來判斷顏色的程式碼寫在自定義控制元件裡面

3,在主程式中呼叫,一句程式碼就可以了

            this.myLED1.LedStatus = true;
            //或者this.myLED1.LedStatus = false;

  

此時程式碼如下:

    public partial class MyLED : UserControl
    {
        public MyLED()
        {
            
            InitializeComponent();

            #region 【1】設定雙緩衝等屬性

            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);

            #endregion

        }

        #region 【2】定義三個欄位

        private Graphics g;
        private Pen p;
        private SolidBrush sb;

        #endregion

        #region 【3】新增一個設定Graphics的方法
        
        private void SetGraphics(Graphics g)
        {
            //設定畫布的屬性
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        }

        #endregion

        #region 【4】根據實際控制元件分析的結果,建立屬性

        private Color ledTrueColor = Color.Green;

        [Category("jason控制元件屬性")]
        [Description("TRUE的時候LED指示燈顏色")]
        public Color LedTrueColor
        {
            get { return ledTrueColor; }
            set
            {
                ledTrueColor = value;
                this.Invalidate();
            }
        }

        private Color ledFalseColor = Color.Red;

        [Category("jason控制元件屬性")]
        [Description("False的時候LED指示燈顏色")]
        public Color LedFalseColor
        {
            get { return ledFalseColor; }
            set
            {
                ledFalseColor = value;
                this.Invalidate();
            }
        }

        private bool ledStatus = true;

        [Category("jason控制元件屬性")]
        [Description("當前的狀態")]
        public bool LedStatus
        {
            get { return ledStatus; }
            set
            {
                ledStatus = value;
                this.Invalidate();
            }
        }

        private Color ledColor = Color.Green;

        [Category("jason控制元件屬性")]
        [Description("LED指示燈演示")]
        public Color LedColor
        {
            get { return ledColor; }
            set
            {
                ledColor = value;
                this.Invalidate();
            }
        }

        private bool isBorder = true;

        [Category("jason控制元件屬性")]
        [Description("是否有邊框")]
        public bool IsBorder
        {
            get { return isBorder; }
            set
            {
                isBorder = value;
                this.Invalidate();
            }
        }

        private int borderWidth = 5;

        [Category("jason控制元件屬性")]
        [Description("圓環的寬度")]
        public int BorderWidth
        {
            get { return borderWidth; }
            set
            {
                borderWidth = value;
                this.Invalidate();
            }
        }

        private int gapWidth = 5;

        [Category("jason控制元件屬性")]
        [Description("間隙的寬度")]
        public int GapWidth
        {
            get { return gapWidth; }
            set
            {
                gapWidth = value;
                this.Invalidate();
            }
        }

        private bool isHighLight = true;

        [Category("jason控制元件屬性")]
        [Description("是否高亮")]
        public bool IsHighLight
        {
            get { return isHighLight; }
            set
            {
                isHighLight = value;
                this.Invalidate();
            }
        }

        private Color centerColor = Color.White;

        [Category("jason控制元件屬性")]
        [Description("漸變中心的顏色")]
        public Color CenterColor
        {
            get { return centerColor; }
            set
            {
                centerColor = value;
                this.Invalidate();
            }
        }

        #endregion

        #region 【5】建立重繪的事件

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            g = e.Graphics;//獲取畫布
            SetGraphics(g);//設定畫布

            #region 1,畫一個圓

            int LEDWidth = Math.Min(this.Width, this.Height);

            Color color = ledStatus ? ledTrueColor : ledFalseColor;
            //sb = new SolidBrush(ledColor);
            sb = new SolidBrush(color);
            RectangleF rec = new RectangleF(1, 1, LEDWidth - 2, LEDWidth - 2);//建立矩形
            g.FillEllipse(sb, rec);//畫圓

            #endregion

            #region 2,在圓裡面畫一個圓環

            //如果有邊框,那就畫一個圓環
            if (isBorder)//引數這裡用欄位或屬性都可以,如果用屬性,程式要都走一些判斷的程式碼
            {
                p = new Pen(this.BackColor, borderWidth);//使用背景色
                //p = new Pen(Color.Red, borderWidth);
                float x = 1 + gapWidth + borderWidth * 0.5f;
                rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                g.DrawEllipse(p, rec);//畫圓環
            }

            #endregion

            #region 3,漸變色繪製,是否高亮

            if (isHighLight)
            {
                GraphicsPath gp = new GraphicsPath();
                float x = isBorder? 1 + gapWidth + borderWidth:1;//使用三元運算來判斷,優化程式碼
                rec = new RectangleF(x, x, LEDWidth - 2 * x, LEDWidth - 2 * x);
                gp.AddEllipse(rec);//把矩形新增到路徑

                //漸變色畫刷,高亮
                PathGradientBrush pgb = new PathGradientBrush(gp);//把路徑傳入

                pgb.CenterColor = this.centerColor;

                //設定有多少組顏色來漸變
                pgb.SurroundColors = new Color[]
                {
                        //ledColor
                        color
                };
                g.FillPath(pgb, gp);
            }

            #endregion


        }

        #endregion
    }