以下是學習筆記:
參考: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
}
