以下是學習筆記:
參考: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 }
四,增加閃爍的效果
效果:
1,增加閃爍要用到的屬性
private bool isFlash = true; [Category("jason控件屬性")] [Description("是否閃爍")] public bool IsFlash { get { return isFlash; } set { isFlash = value; this.Invalidate(); } } private int flashInterval = 500; [Category("jason控件屬性")] [Description("閃爍的頻率")] public int FlashInterval { get { return flashInterval; } set { flashInterval = value; timer.Interval = flashInterval;//timer的時間間隔要放在這里 this.Invalidate(); } } private Color[] lampColor = new Color[] { }; [Category("jason控件屬性")] [Description("閃爍燈的幾種顏色,當需要閃爍時,至少需要2個及以上顏色,不需要閃爍則至少需要1個顏色")] public Color[] LampColor { get { return lampColor; } set { if (value == null || value.Length <= 0) return; lampColor = value; this.Invalidate(); } }
2,判斷是否閃爍
3,timer事件
private void Timer_Tick(object sender, EventArgs e) { intColorIndex++; if (intColorIndex >= lampColor.Length) { intColorIndex = 0; } this.Invalidate(); }
4,完整代碼:
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); timer.Enabled = true; timer.Tick += Timer_Tick; #endregion } private void Timer_Tick(object sender, EventArgs e) { intColorIndex++; if (intColorIndex >= lampColor.Length) { intColorIndex = 0; } this.Invalidate(); } #region 【2】定義三個字段 private Graphics g; private Pen p; private SolidBrush sb; Timer timer=new Timer(); private int intColorIndex = 0; #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(); } } private bool isFlash = true; [Category("jason控件屬性")] [Description("是否閃爍")] public bool IsFlash { get { return isFlash; } set { isFlash = value; this.Invalidate(); } } private int flashInterval = 500; [Category("jason控件屬性")] [Description("閃爍的頻率")] public int FlashInterval { get { return flashInterval; } set { flashInterval = value; timer.Interval = flashInterval;//timer的時間間隔要放在這里 this.Invalidate(); } } private Color[] lampColor = new Color[] { }; [Category("jason控件屬性")] [Description("閃爍燈的幾種顏色,當需要閃爍時,至少需要2個及以上顏色,不需要閃爍則至少需要1個顏色")] public Color[] LampColor { get { return lampColor; } set { if (value == null || value.Length <= 0) return; lampColor = 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; if (isFlash) { lampColor=new Color[]{color,Color.Yellow}; color = lampColor[intColorIndex]; } 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);//把路徑傳入 Color[] surroundColor = new Color[] {color}; pgb.CenterColor = this.centerColor; //設置有多少組顏色來漸變 pgb.SurroundColors = surroundColor; g.FillPath(pgb, gp); } #endregion } #endregion }