前提 入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。 開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control 如果覺得寫的還行,請點個 star 支持一下吧 歡迎前來交流探討: 企鵝群568015492 目錄 ...
前提
入行已經7,8年了,一直想做一套漂亮點的自定義控制項,於是就有了本系列文章。
開源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control
如果覺得寫的還行,請點個 star 支持一下吧
目錄
https://www.cnblogs.com/bfyx/p/11364884.html
準備工作
GDI+需要有一點瞭解,不知道的可以百度瞅瞅
開始
添加一個用戶控制項,命名UCSwitch
添加一個枚舉用以控制樣式
1 public enum SwitchType 2 { 3 /// <summary> 4 /// 橢圓 5 /// </summary> 6 Ellipse, 7 /// <summary> 8 /// 四邊形 9 /// </summary> 10 Quadrilateral, 11 /// <summary> 12 /// 橫線 13 /// </summary> 14 Line 15 }
添加屬性
1 [Description("選中改變事件"), Category("自定義")] 2 public event EventHandler CheckedChanged; 3 private Color m_trueColor = Color.FromArgb(34, 163, 169); 4 5 [Description("選中時顏色"), Category("自定義")] 6 public Color TrueColor 7 { 8 get { return m_trueColor; } 9 set 10 { 11 m_trueColor = value; 12 Refresh(); 13 } 14 } 15 16 private Color m_falseColor = Color.FromArgb(111, 122, 126); 17 18 [Description("沒有選中時顏色"), Category("自定義")] 19 public Color FalseColor 20 { 21 get { return m_falseColor; } 22 set 23 { 24 m_falseColor = value; 25 Refresh(); 26 } 27 } 28 29 private bool m_checked; 30 31 [Description("是否選中"), Category("自定義")] 32 public bool Checked 33 { 34 get { return m_checked; } 35 set 36 { 37 m_checked = value; 38 Refresh(); 39 if (CheckedChanged != null) 40 { 41 CheckedChanged(this, null); 42 } 43 } 44 } 45 46 private string[] m_texts; 47 48 [Description("文本值,當選中或沒有選中時顯示,必須是長度為2的數組"), Category("自定義")] 49 public string[] Texts 50 { 51 get { return m_texts; } 52 set 53 { 54 m_texts = value; 55 Refresh(); 56 } 57 } 58 private SwitchType m_switchType = SwitchType.Ellipse; 59 60 [Description("顯示類型"), Category("自定義")] 61 public SwitchType SwitchType 62 { 63 get { return m_switchType; } 64 set 65 { 66 m_switchType = value; 67 Refresh(); 68 } 69 } 70 71 public override Font Font 72 { 73 get 74 { 75 return base.Font; 76 } 77 set 78 { 79 base.Font = value; 80 Refresh(); 81 } 82 }
重繪
1 protected override void OnPaint(PaintEventArgs e) 2 { 3 base.OnPaint(e); 4 var g = e.Graphics; 5 g.SetGDIHigh(); 6 if (m_switchType == HZH_Controls.Controls.SwitchType.Ellipse) 7 { 8 var fillColor = m_checked ? m_trueColor : m_falseColor; 9 GraphicsPath path = new GraphicsPath(); 10 path.AddLine(new Point(this.Height / 2, 1), new Point(this.Width - this.Height / 2, 1)); 11 path.AddArc(new Rectangle(this.Width - this.Height - 1, 1, this.Height - 2, this.Height - 2), -90, 180); 12 path.AddLine(new Point(this.Width - this.Height / 2, this.Height - 1), new Point(this.Height / 2, this.Height - 1)); 13 path.AddArc(new Rectangle(1, 1, this.Height - 2, this.Height - 2), 90, 180); 14 g.FillPath(new SolidBrush(fillColor), path); 15 16 string strText = string.Empty; 17 if (m_texts != null && m_texts.Length == 2) 18 { 19 if (m_checked) 20 { 21 strText = m_texts[0]; 22 } 23 else 24 { 25 strText = m_texts[1]; 26 } 27 } 28 29 if (m_checked) 30 { 31 g.FillEllipse(Brushes.White, new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4)); 32 if (string.IsNullOrEmpty(strText)) 33 { 34 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 35 } 36 else 37 { 38 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font); 39 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2; 40 g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY)); 41 } 42 } 43 else 44 { 45 g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4)); 46 if (string.IsNullOrEmpty(strText)) 47 { 48 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 49 } 50 else 51 { 52 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font); 53 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2; 54 g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY)); 55 } 56 } 57 } 58 else if (m_switchType == HZH_Controls.Controls.SwitchType.Quadrilateral) 59 { 60 var fillColor = m_checked ? m_trueColor : m_falseColor; 61 GraphicsPath path = new GraphicsPath(); 62 int intRadius = 5; 63 path.AddArc(0, 0, intRadius, intRadius, 180f, 90f); 64 path.AddArc(this.Width - intRadius - 1, 0, intRadius, intRadius, 270f, 90f); 65 path.AddArc(this.Width - intRadius - 1, this.Height - intRadius - 1, intRadius, intRadius, 0f, 90f); 66 path.AddArc(0, this.Height - intRadius - 1, intRadius, intRadius, 90f, 90f); 67 68 g.FillPath(new SolidBrush(fillColor), path); 69 70 string strText = string.Empty; 71 if (m_texts != null && m_texts.Length == 2) 72 { 73 if (m_checked) 74 { 75 strText = m_texts[0]; 76 } 77 else 78 { 79 strText = m_texts[1]; 80 } 81 } 82 83 if (m_checked) 84 { 85 GraphicsPath path2 = new GraphicsPath(); 86 path2.AddArc(this.Width - this.Height - 1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f); 87 path2.AddArc(this.Width - 1 - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f); 88 path2.AddArc(this.Width - 1 - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f); 89 path2.AddArc(this.Width - this.Height - 1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f); 90 g.FillPath(Brushes.White, path2); 91 92 if (string.IsNullOrEmpty(strText)) 93 { 94 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 95 } 96 else 97 { 98 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font); 99 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2; 100 g.DrawString(strText, Font, Brushes.White, new Point((this.Height - 2 - 4) / 2, intTextY)); 101 } 102 } 103 else 104 { 105 GraphicsPath path2 = new GraphicsPath(); 106 path2.AddArc(1 + 2, 1 + 2, intRadius, intRadius, 180f, 90f); 107 path2.AddArc(this.Height - 2 - intRadius, 1 + 2, intRadius, intRadius, 270f, 90f); 108 path2.AddArc(this.Height - 2 - intRadius, this.Height - 2 - intRadius - 1, intRadius, intRadius, 0f, 90f); 109 path2.AddArc(1 + 2, this.Height - 2 - intRadius - 1, intRadius, intRadius, 90f, 90f); 110 g.FillPath(Brushes.White, path2); 111 112 //g.FillEllipse(Brushes.White, new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4)); 113 if (string.IsNullOrEmpty(strText)) 114 { 115 g.DrawEllipse(new Pen(Color.White, 2), new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 116 } 117 else 118 { 119 System.Drawing.SizeF sizeF = g.MeasureString(strText.Replace(" ", "A"), Font); 120 int intTextY = (this.Height - (int)sizeF.Height) / 2 + 2; 121 g.DrawString(strText, Font, Brushes.White, new Point(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - (int)sizeF.Width / 2, intTextY)); 122 } 123 } 124 } 125 else 126 { 127 var fillColor = m_checked ? m_trueColor : m_falseColor; 128 int intLineHeight = (this.Height - 2 - 4) / 2; 129 130 GraphicsPath path = new GraphicsPath(); 131 path.AddLine(new Point(this.Height / 2, (this.Height - intLineHeight) / 2), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2)); 132 path.AddArc(new Rectangle(this.Width - this.Height / 2 - intLineHeight - 1, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), -90, 180); 133 path.AddLine(new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight), new Point(this.Width - this.Height / 2, (this.Height - intLineHeight) / 2 + intLineHeight)); 134 path.AddArc(new Rectangle(this.Height / 2, (this.Height - intLineHeight) / 2, intLineHeight, intLineHeight), 90, 180); 135 g.FillPath(new SolidBrush(fillColor), path); 136 137 if (m_checked) 138 { 139 g.FillEllipse(new SolidBrush(fillColor), new Rectangle(this.Width - this.Height - 1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4)); 140 g.FillEllipse(Brushes.White, new Rectangle(this.Width - 2 - (this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 - 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 141 } 142 else 143 { 144 g.FillEllipse(new SolidBrush(fillColor), new Rectangle(1 + 2, 1 + 2, this.Height - 2 - 4, this.Height - 2 - 4)); 145 g.FillEllipse(Brushes.White, new Rectangle((this.Height - 2 - 4) / 2 - ((this.Height - 2 - 4) / 2) / 2 + 4, (this.Height - 2 - (this.Height - 2 - 4) / 2) / 2 + 1, (this.Height - 2 - 4) / 2, (this.Height - 2 - 4) / 2)); 146 } 147 } 148 }
處理一下點擊事件
1 void UCSwitch_MouseDown(object sender, MouseEventArgs e) 2 { 3 Checked = !Checked; 4 }
完整代碼
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Drawing; 5 using System.Data; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Drawing.Drawing2D; 10 11 namespace HZH_Controls.Controls 12 { 13 [DefaultEvent("CheckedChanged")] 14 public partial class UCSwitch : UserControl 15 { 16 [Description("選中改變事件"), Category("自定義")] 17 public event EventHandler CheckedChanged; 18 private Color m_trueColor = Color.FromArgb(34, 163, 169); 19 20 [Description("選中時顏色"), Category("自定義")] 21 public Color TrueColor 22 { 23 get { return m_trueColor; } 24 set 25 { 26 m_trueColor = value; 27 Refresh(); 28 } 29 } 30 31 private Color m_falseColor = Color.FromArgb(111, 122, 126); 32 33 [Description("沒有選中時顏色"), Category("自定義")] 34 public Color FalseColor 35 { 36 get { return m_falseColor; } 37 set 38 { 39 m_falseColor = value; 40 Refresh(); 41 } 42 } 43 44 private bool m_checked; 45 46 [Description("是否選中"), Category("自定義")] 47 public bool Checked 48 { 49 get { return m_checked; } 50 set 51 { 52 m_checked = value; 53 Refresh(); 54 if (CheckedChanged != null) 55 { 56 CheckedChanged(this, null); 57 } 58 } 59 } 60 61 private string[] m_texts; 62 63 [Description("文本值,當選中或沒有選中時顯示,必須是長度為2的數組"), Category("自定義")] 64 public string[] Texts 65 { 66 get { return m_texts; } 67 set 68 { 69 m_texts = value; 70 Refresh(); 71 } 72 } 73 private SwitchType m_switchType = SwitchType.Ellipse; 74 75 [Description("顯示類型"), Category("自定義")] 76 public SwitchType SwitchType 77 { 78 get { return m_switchType; } 79 set 80 { 81 m_switchType = value; 82 Refresh(); 83 } 84 } 85