下面分两步制作这个按钮。
A. 目标
想了一下,即将制作的圆形按钮需要满足几个要求:
i. 按钮呈现圆形或椭圆形,具体形状参数可调;
ii. 按钮用不同的填充色来响应鼠标进入或者离开事件;
iii. 按钮通过改变边的颜色来显示是否获取焦点状态;
iv. 按钮通过改变填充色的亮度来区分按钮是否按下。
B. 实现代码
具体的制作思路大致如下:
i. 成员变量:
Rectangle
bool
bool
bool
ii. 属性:
(a).形状;
(b).填充色;
(c).边框。
iii. 构造函数
(a).按钮风格设定;
(b).成员变量初始化;
iv. 部分函数重写
(a).控件绘制OnPaint;
(b).鼠标相关函数;
v. 自定义函数
(a).图案填充;
(b).绘制边框;
(c).调整控件大小;
代码如下:
1 using System;
2 using System.Collections.Generic;
3 using System.ComponentModel;
4 using System.Diagnostics;
5 using System.Linq;
6 using System.Text;
7
8 using System.Windows.Forms;
9 using System.Drawing;
10 using System.Drawing.Drawing2D;
11
12 namespace 章鱼.Forms
13 {
14 public partial class RoundButton : Button
15 {
16 #region --成员变量--
17
18 RectangleF rect = new RectangleF();//控件矩形
19 bool mouseEnter;//鼠标是否进入控件区域的标志
20 bool buttonPressed;//按钮是否按下
21 bool buttonClicked;//按钮是否被点击
22 #endregion
23
24 #region --属性--
25
26 #region 形状
27
28 /// <summary>
29 /// 设置或获取圆形按钮的圆的边距离方框边的距离
30 /// </summary>
31 [Browsable(true), DefaultValue(2)]
32 [Category("Appearance")]
33 public int DistanceToBorder { get; set; }
34
35 #endregion
36
37 #region 填充色
38
39 /// <summary>
40 /// 获取或设置按钮主体颜色
41 /// </summary>
42 /// <value>The color of the focus.</value>
43 [Browsable(true), DefaultValue(typeof(Color), "DodgerBlue"), Description("按钮主体渐变起始颜色")]
44 [Category("Appearance")]
45 public Color ButtonCenterColorEnd { get; set; }
46
47 /// <summary>
48 /// 获取或设置按钮主体颜色
49 /// </summary>
50 [Browsable(true), DefaultValue(typeof(Color), "CornflowerBlue"), Description("按钮主体渐变终点颜色")]
51 [Category("Appearance")]
52 public Color ButtonCenterColorStart { get; set; }
53
54 /// <summary>
55 /// 获取或设置按钮主体颜色渐变方向
56 /// </summary>
57 [Browsable(true), DefaultValue(90), Description("按钮主体颜色渐变方向,X轴顺时针开始")]
58 [Category("Appearance")]
59 public int GradientAngle { get; set; }
60
61 /// <summary>
62 /// 是否显示中间标志
63 /// </summary>
64 [Browsable(true), DefaultValue(typeof(bool), "true"), Description("是否显示中间标志")]
65 [Category("Appearance")]
66 public bool IsShowIcon { get; set; }
67
68 /// <summary>
69 /// 按钮中间标志填充色
70 /// </summary>
71 [Browsable(true), DefaultValue(typeof(Color), "Black"), Description("按钮中间标志填充色")]
72 [Category("Appearance")]
73 public Color IconColor { get; set; }
74
75
76 #endregion
77
78 #region 边框
79
80 /// <summary>
81 /// 获取或设置边框大小
82 /// </summary>
83 [Browsable(true), DefaultValue(4), Description("按钮边框大小")]
84 [Category("Appearance")]
85 public int BorderWidth { get; set; }
86
87 /// <summary>
88 /// 获取或设置按钮边框颜色
89 /// </summary>
90 /// <value>The color of the focus.</value>
91 [Browsable(true), DefaultValue(typeof(Color), "Black"), Description("按钮边框颜色")]
92 [Category("Appearance")]
93 public Color BorderColor { get; set; }
94
95 /// <summary>
96 /// 获取或设置边框透明度
97 /// </summary>
98 [Browsable(true), DefaultValue(200), Description("设置边框透明度:0-255")]
99 [Category("Appearance")]
100 public int BorderTransparent { get; set; }
101
102 /// <summary>
103 /// 获取或设置按钮获取焦点后边框颜色
104 /// </summary>
105 /// <value>The color of the focus.</value>
106 [Browsable(true), DefaultValue(typeof(Color), "Orange"), Description("按钮获得焦点后的边框颜色")]
107 [Category("Appearance")]
108 public Color FocusBorderColor { get; set; }
109
110 #endregion
111
112 #endregion
113
114 #region --构造函数--
115 /// <summary>
116 /// 构造函数
117 /// </summary>
118 public RoundButton()
119 {
120 // 控件风格
121 SetStyle(ControlStyles.SupportsTransparentBackColor, true);
122 SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
123 SetStyle(ControlStyles.AllPaintingInWmPaint, true);
124 SetStyle(ControlStyles.ResizeRedraw, true);
125 SetStyle(ControlStyles.UserPaint, true);
126 //初始值设定
127 this.Height = this.Width = 80;
128
129 DistanceToBorder = 4;
130 ButtonCenterColorStart = Color.CornflowerBlue;
131 ButtonCenterColorEnd = Color.DodgerBlue;
132 BorderColor = Color.Black;
133 FocusBorderColor = Color.Orange;
134 IconColor = Color.Black;
135 BorderWidth = 4;
136 BorderTransparent = 200;
137 GradientAngle = 90;
138
139 mouseEnter = false;
140 buttonPressed = false;
141 buttonClicked = false;
142 IsShowIcon = true;
143
144 InitializeComponent();
145 }
146 #endregion
147
148 #region --重写部分事件--
149
150 #region OnPaint事件
151
152 /// <summary>
153 /// 控件绘制
154 /// </summary>
155 /// <param name="pevent"></param>
156 protected override void OnPaint(PaintEventArgs pevent)
157 {
158 //base.OnPaint(pevent);
159 base.OnPaintBackground(pevent);
160
161 Graphics g = pevent.Graphics;
162 g.InterpolationMode = InterpolationMode.HighQualityBicubic;
163 g.SmoothingMode = SmoothingMode.AntiAlias;//抗锯齿
164
165 myResize();//调整圆形区域
166
167 var brush = new LinearGradientBrush(rect, ButtonCenterColorStart, ButtonCenterColorEnd, GradientAngle);
168
169 PaintShape(g, brush, rect);//绘制按钮中心区域
170
171 DrawBorder(g);//绘制边框
172
173 DrawStateIcon(g);//绘制按钮功能标志
174
175 if (mouseEnter)
176 {
177 DrawHighLight(g);//绘制高亮区域
178 DrawStateIcon(g);//绘制按钮功能标志
179 }
180 }
181
182 #endregion
183
184 #region 鼠标
185
186 /// <summary>
187 /// 鼠标点击事件
188 /// </summary>
189 /// <param name="e"></param>
190 protected override void OnMouseClick(MouseEventArgs e)
191 {
192 base.OnMouseClick(e);
193 buttonClicked = !buttonClicked;
194 }
195 /// <summary>
196 /// Raises the <see cref="E:System.Windows.Forms.Control.MouseUp"/> event.
197 /// </summary>
198 /// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
199 protected override void OnMouseUp(MouseEventArgs e)
200 {
201 base.OnMouseUp(e);
202 if (e.Button != MouseButtons.Left) return;
203 buttonPressed = false;
204 base.Invalidate();
205 }
206
207 /// <summary>
208 /// Raises the <see cref="E:System.Windows.Forms.Control.MouseDown"/> event.
209 /// </summary>
210 /// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
211 protected override void OnMouseDown(MouseEventArgs e)
212 {
213 base.OnMouseDown(e);
214 if (e.Button != MouseButtons.Left) return;
215 buttonPressed = true;
216 }
217
218 /// <summary>
219 /// 鼠标进入按钮
220 /// </summary>
221 /// <param name="e"></param>
222 protected override void OnMouseEnter(EventArgs e)
223 {
224 base.OnMouseEnter(e);
225 mouseEnter = true;
226 }
227
228 /// <summary>
229 /// 鼠标离开控件
230 /// </summary>
231 /// <param name="e"></param>
232 protected override void OnMouseLeave(EventArgs e)
233 {
234 base.OnMouseLeave(e);
235 mouseEnter = false;
236 }
237
238 #endregion
239 #endregion
240
241 #region --自定义函数--
242
243 /// <summary>
244 /// 绘制中心区域标志
245 /// </summary>
246 /// <param name="g"></param>
247 private void DrawStateIcon(Graphics g)
248 {
249 if (IsShowIcon)
250 {
251 if (buttonClicked)
252 {
253 GraphicsPath startIconPath = new GraphicsPath();
254 int W = base.Width / 3;
255 Point p1 = new Point(W, W);
256 Point p2 = new Point(2 * W, W);
257 Point p3 = new Point(2 * W, 2 * W);
258 Point p4 = new Point(W, 2 * W);
259 Point[] pts = { p1, p2, p3, p4 };
260 startIconPath.AddLines(pts);
261 Brush brush = new SolidBrush(IconColor);
262 g.FillPath(brush, startIconPath);
263 }
264 else
265 {
266 GraphicsPath stopIconPath = new GraphicsPath();
267 int W = base.Width / 4;
268 Point p1 = new Point(3 * W / 2, W);
269 Point p2 = new Point(3 * W / 2, 3 * W);
270 Point p3 = new Point(3 * W, 2 * W);
271 Point[] pts = { p1, p2, p3, };
272 stopIconPath.AddLines(pts);
273 Brush brush = new SolidBrush(IconColor);
274 g.FillPath(brush, stopIconPath);
275 }
276 }
277 }
278
279 /// <summary>
280 /// 重新确定控件大小
281 /// </summary>
282 protected void myResize()
283 {
284 int x = DistanceToBorder;
285 int y = DistanceToBorder;
286 int width = this.Width - 2 * DistanceToBorder;
287 int height = this.Height - 2 * DistanceToBorder;
288 rect = new RectangleF(x, y, width, height);
289 }
290
291 /// <summary>
292 /// 绘制高亮效果
293 /// </summary>
294 /// <param name="g">Graphic对象</param>
295 protected virtual void DrawHighLight(Graphics g)
296 {
297 RectangleF highlightRect = rect;
298 highlightRect.Inflate(-BorderWidth / 2, -BorderWidth / 2);
299 Brush brush = Brushes.DodgerBlue;
300 if (buttonPressed)
301 {
302 brush = new LinearGradientBrush(rect, ButtonCenterColorStart, ButtonCenterColorEnd, GradientAngle);
303 }
304
305 else
306 {
307 brush = new LinearGradientBrush(rect, Color.FromArgb(60, Color.White),
308 Color.FromArgb(60, Color.White), GradientAngle);
309 }
310 PaintShape(g, brush, highlightRect);
311 }
312
313 /// <summary>
314 /// 绘制边框
315 /// </summary>
316 /// <param name="g">Graphics对象</param>
317 protected virtual void DrawBorder(Graphics g)
318 {
319 Pen p = new Pen(BorderColor);
320 if (Focused)
321 {
322 p.Color = FocusBorderColor;//外圈获取焦点后的颜色
323 p.Width = BorderWidth;
324 PaintShape(g, p, rect);
325 }
326 else
327 {
328 p.Width = BorderWidth;
329 PaintShape(g, p, rect);
330 }
331
332 }
333
334 /// <summary>
335 ///
336 /// </summary>
337 /// <param name="g">Graphic对象</param>
338 protected virtual void DrawPressState(Graphics g)
339 {
340 RectangleF pressedRect = rect;
341 pressedRect.Inflate(-2, -2);
342 Brush brush = new LinearGradientBrush(rect, Color.FromArgb(60, Color.White),
343 Color.FromArgb(60, Color.White), GradientAngle);
344 PaintShape(g, brush, pressedRect);
345 }
346
347 /// <summary>
348 /// 绘制图形
349 /// </summary>
350 /// <param name="g">Graphics对象</param>
351 /// <param name="pen">Pen对象</param>
352 /// <param name="rect">RectangleF对象</param>
353 protected virtual void PaintShape(Graphics g, Pen pen, RectangleF rect)
354 {
355 g.DrawEllipse(pen, rect);
356 }
357
358 /// <summary>
359 /// 绘制图形
360 /// </summary>
361 /// <param name="g">Graphics对象</param>
362 /// <param name="brush">Brush对象</param>
363 /// <param name="rect">Rectangle对象</param>
364 protected virtual void PaintShape(Graphics g, Brush brush, RectangleF rect)
365 {
366 g.FillEllipse(brush, rect);
367 }
368
369 #endregion
370 }
371 }