制作一个播放器的控制按钮组合控件 较好的封装子控件 并提供公开属性更换外观
组合控件还差按钮上的图形 比如中间的播放图标 上一个 下一个 打开 停止的图标,控件使用alpha混合和渐变
组合控件一共上下左右四个按钮 自身作为中间的按钮使用,并且可以适应各种宽度和高度
我的思路是这样的:总共有五个类 组合控件MP3Buttons 上下左右四个按钮类 ,主要实现一个周边按钮 其它3个按钮继承自这个按钮,并重写一个方法就可以了,所以主要是实现2个类 组合按钮类,任意一个周边按钮
1.先设计一个左边按钮的类 LeftButton:UserControl 本可以继承Control类 不过Control不支持背景透明 UserControl支持背景透明,在Resize事件中限制控件的区域
2.创建RightButton TopButton BottomButton 它们继承自LeftButton
3.创建MP3Buttons组合控件 继承自UserControl 设计对外属性以更改控件的外观 设计各按钮的单击事件
一.LeftButton的实现
代码
1
internal
partial
class
LeftButton : UserControl
2
{
3
private
enum
MouseStatus { Eneter, Leave, Down, Up }
4
5
private
Color _themeColor
=
Color.Black;
6
private
Color _normalColor
=
Color.FromArgb(
200
, Color.Black);
7
private
Color _enterColor
=
Color.FromArgb(
100
, Color.Black);
8
private
Color _dowmColor
=
Color.FromArgb(
150
, Color.Black);
9
private
MouseStatus _state
=
MouseStatus.Leave;
10
public
GraphicsPath _borderPath;
11
12
public
Color ThemeColor
13
{
14
set
15
{
16
_themeColor
=
value;
17
_normalColor
=
Color.FromArgb(
200
, _themeColor);
18
_enterColor
=
Color.FromArgb(
100
, _themeColor);
19
_dowmColor
=
Color.FromArgb(
150
, _themeColor);
20
Refresh();
21
}
22
get
{
return
_themeColor; }
23
}
24
25
public
LeftButton()
26
{
27
InitializeComponent();
28
SetStyle(ControlStyles.DoubleBuffer
|
ControlStyles.OptimizedDoubleBuffer
|
ControlStyles.AllPaintingInWmPaint
|
ControlStyles.SupportsTransparentBackColor,
true
);
29
UpdateStyles();
30
}
31
32
protected
override
void
OnPaint(PaintEventArgs pe)
33
{
34
Graphics g
=
pe.Graphics;
35
g.SmoothingMode
=
SmoothingMode.HighQuality;
36
GraphicsPath path
=
new
GraphicsPath();
37
path.AddEllipse(
this
.ClientRectangle);
38
39
PathGradientBrush pgBrunsh
=
new
PathGradientBrush(path);
40
pgBrunsh.CenterColor
=
Color.FromArgb(
0
, ThemeColor);
41
switch
(_state)
42
{
43
case
MouseStatus.Leave:
44
{
45
pgBrunsh.SurroundColors
=
new
Color[] { _normalColor };
46
g.FillRectangle(pgBrunsh,
this
.ClientRectangle);
47
break
;
48
}
49
case
MouseStatus.Eneter:
50
{
51
pgBrunsh.SurroundColors
=
new
Color[] { _enterColor };
52
g.FillRectangle(pgBrunsh,
this
.ClientRectangle);
53
break
;
54
}
55
case
MouseStatus.Down:
56
{
57
pgBrunsh.SurroundColors
=
new
Color[] { _dowmColor };
58
g.FillRectangle(pgBrunsh,
this
.ClientRectangle);
59
break
;
60
}
61
case
MouseStatus.Up:
62
{
63
pgBrunsh.SurroundColors
=
new
Color[] { _enterColor };
64
g.FillRectangle(pgBrunsh,
this
.ClientRectangle);
65
break
;
66
}
67
default
:
68
{
69
pgBrunsh.SurroundColors
=
new
Color[] { _normalColor };
70
g.FillRectangle(pgBrunsh,
this
.ClientRectangle);
71
break
;
72
}
73
}
74
try
75
{
76
g.DrawPath(
new
Pen(
new
SolidBrush(_themeColor),
1
), _borderPath);
77
}
78
catch
79
{
80
}
81
g.SmoothingMode
=
SmoothingMode.HighQuality;
82
base
.OnPaint(pe);
83
}
84
protected
override
void
OnResize(EventArgs e)
85
{
86
GraphicsPath path1
=
new
GraphicsPath();
87
GraphicsPath path2
=
new
GraphicsPath();
88
Rectangle rect
=
new
Rectangle(
this
.Width
/
3
,
this
.Height
/
3
,
this
.Width
/
3
,
this
.Height
/
3
);
89
path1.AddPie(
0
,
0
,
this
.Width,
this
.Height,
135
,
90
);
90
_borderPath
=
path1;
91
this
.Refresh();
92
float
a
=
(
float
)
this
.Width
/
3
;
93
float
b
=
(
float
)
this
.Height
/
3
;
94
path2.AddPie(a, b, a, b,
135
,
90
);
95
Region region
=
new
Region(path1);
96
region.Exclude(path2);
97
this
.Region
=
region;
98
base
.OnResize(e);
99
}
100
protected
override
void
OnMouseEnter(EventArgs e)
101
{
102
_state
=
MouseStatus.Eneter;
103
this
.Refresh();
104
base
.OnMouseEnter(e);
105
}
106
protected
override
void
OnMouseLeave(EventArgs e)
107
{
108
_state
=
MouseStatus.Leave;
109
this
.Refresh();
110
base
.OnMouseLeave(e);
111
}
112
protected
override
void
OnMouseDown(MouseEventArgs e)
113
{
114
_state
=
MouseStatus.Down;
115
this
.Refresh();
116
base
.OnMouseDown(e);
117
}
118
protected
override
void
OnMouseUp(MouseEventArgs e)
119
{
120
_state
=
MouseStatus.Up;
121
this
.Refresh();
122
base
.OnMouseUp(e);
123
}
124
protected
override
void
OnClick(EventArgs e)
125
{
126
base
.OnClick(e);
127
_state
=
MouseStatus.Leave;
128
Invalidate();
129
}
130
}
此类有一个ThemeColor属性 通过设置此属性更改其外观
二.实现其它周边3个按钮 只需要重写一个方法以更改有效区域
代码
1
internal
partial
class
RightButton :LeftButton
2
{
3
public
RightButton()
4
{
5
InitializeComponent();
6
}
7
protected
override
void
OnResize(EventArgs e)
8
{
9
GraphicsPath path1
=
new
GraphicsPath();
10
GraphicsPath path2
=
new
GraphicsPath();
11
Rectangle rect
=
new
Rectangle(
this
.Width
/
3
,
this
.Height
/
3
,
this
.Width
/
3
,
this
.Height
/
3
);
12
path1.AddPie(
0
,
0
,
this
.Width,
this
.Height,
315
,
90
);
13
_borderPath
=
path1;
14
this
.Refresh();
15
float
a
=
(
float
)
this
.Width
/
3
;
16
float
b
=
(
float
)
this
.Height
/
3
;
17
path2.AddPie(a, b, a, b,
310
,
100
);
18
Region region
=
new
Region(path1);
19
region.Exclude(path2);
20
this
.Region
=
region;
21
}
22
}
代码
1
internal
partial
class
TopButton : LeftButton
2
{
3
public
TopButton()
4
{
5
InitializeComponent();
6
}
7
8
protected
override
void
OnResize(EventArgs e)
9
{
10
GraphicsPath path1
=
new
GraphicsPath();
11
GraphicsPath path2
=
new
GraphicsPath();
12
Rectangle rect
=
new
Rectangle(
this
.Width
/
3
,
this
.Height
/
3
,
this
.Width
/
3
,
this
.Height
/
3
);
13
path1.AddPie(
0
,
0
,
this
.Width,
this
.Height,
225
,
90
);
14
_borderPath
=
path1;
15
this
.Refresh();
16
float
a
=
(
float
)
this
.Width
/
3
;
17
float
b
=
(
float
)
this
.Height
/
3
;
18
path2.AddPie(a, b, a, b,
215
,
100
);
19
Region region
=
new
Region(path1);
20
region.Exclude(path2);
21
this
.Region
=
region;
22
}
23
}
代码
1
internal
partial
class
BottomButton : LeftButton
2
{
3
public
BottomButton()
4
{
5
InitializeComponent();
6
}
7
protected
override
void
OnResize(EventArgs e)
8
{
9
GraphicsPath path1
=
new
GraphicsPath();
10
GraphicsPath path2
=
new
GraphicsPath();
11
Rectangle rect
=
new
Rectangle(
this
.Width
/
3
,
this
.Height
/
3
,
this
.Width
/
3
,
this
.Height
/
3
);
12
path1.AddPie(
0
,
0
,
this
.Width,
this
.Height,
45
,
90
);
13
_borderPath
=
path1;
14
this
.Refresh();
15
float
a
=
(
float
)
this
.Width
/
3
;
16
float
b
=
(
float
)
this
.Height
/
3
;
17
path2.AddPie(a, b, a, b,
40
,
100
);
18
Region region
=
new
Region(path1);
19
region.Exclude(path2);
20
this
.Region
=
region;
21
}
22
}
这样 周边四个按钮就完成了
三.设计MP3Buttons:UserControl
把4个按钮从工具箱中拖到控件上 并设置它们的Dock属性为Fill 充满整个控件
此时在MP3Buttons上有4个实例化的子控件 LeftButton1 RightButton1 TopButton1 BottomButton1
1.设计辅助类型和字段
代码
1
private
enum
ButtonSta { Down, Up }
2
private
bool
_isPlaying
=
false
;
3
private
ButtonSta _state
=
ButtonSta.Up;
4
private
Color _themeColor
=
Color.Red;
5
private
Color _downColor
=
Color.FromArgb(
100
, Color.Red);
6
private
Color _surroundingColor
=
Color.Black;
7
private
EventHandler _themeColorChanged
=
null
;
8
private
EventHandler _surroundingColorChanged
=
null
;
2.属性和构造函数 有2个属性 一个用于更改自身的外观 一个用于更改周边按钮的外观,这样可以形成外观组合 获得更丰富的外观
代码
1
public
Color ThemeColor
2
{
3
set
4
{
5
_themeColor
=
value;
6
_downColor
=
Color.FromArgb(
100
, _themeColor);
7
Invalidate();
8
if
(_themeColorChanged
!=
null
)
9
_themeColorChanged(
this
,
new
EventArgs());
10
}
11
get
12
{
13
return
_themeColor;
14
}
15
}
16
public
Color SurroundingColor
17
{
18
set
19
{
20
_surroundingColor
=
value;
21
leftButtonl1.ThemeColor
=
_surroundingColor;
22
rightButton1.ThemeColor
=
_surroundingColor;
23
topButton1.ThemeColor
=
_surroundingColor;
24
buttomButton1.ThemeColor
=
_surroundingColor;
25
26
if
(_surroundingColorChanged
!=
null
)
27
_surroundingColorChanged(
this
,
new
EventArgs());
28
}
29
get
30
{
31
return
_surroundingColor;
32
}
33
}
34
public
bool
IsPlaying
35
{
36
get
{
return
_isPlaying; }
37
set
38
{
39
_isPlaying
=
value;
40
this
.Invalidate();
41
}
42
}
43
public
Mp3Buttons()
44
{
45
InitializeComponent();
46
SetStyle(ControlStyles.DoubleBuffer
|
ControlStyles.OptimizedDoubleBuffer
|
ControlStyles.AllPaintingInWmPaint
|
ControlStyles.SupportsTransparentBackColor,
true
);
47
UpdateStyles();
48
leftButtonl1.ThemeColor
=
_surroundingColor;
49
rightButton1.ThemeColor
=
_surroundingColor;
50
topButton1.ThemeColor
=
_surroundingColor;
51
buttomButton1.ThemeColor
=
_surroundingColor;
52
53
54
}
3.设计事件 为了提供更好的封装 组合按钮类是公开的密封类 也不允许外部访问其子控件,由此控件对外提供六个事件 方便使用
这6个事件是 LeftButtonClick RightButtonClick TopButtonClick ButtomClick ThemeColorChanged SurroundingColorChanged
代码
1
public
event
EventHandler ThemeColorChanged
2
{
3
add { _themeColorChanged
+=
value; }
4
remove { _themeColorChanged
=
value; }
5
}
6
public
event
EventHandler SurroundingColorChanged
7
{
8
add { _surroundingColorChanged
+=
value; }
9
remove { _surroundingColorChanged
-=
value; }
10
}
11
public
event
EventHandler LeftButtonClick
12
{
13
add {
this
.leftButtonl1.Click
+=
value; }
14
remove {
this
.leftButtonl1.Click
-=
value; }
15
}
16
public
event
EventHandler RightButtonClick
17
{
18
add { rightButton1.Click
+=
value; }
19
remove { rightButton1.Click
-=
value; }
20
}
21
public
event
EventHandler TopButtonClick
22
{
23
add { topButton1.Click
+=
value; }
24
remove { topButton1.Click
-=
value; }
25
}
26
public
event
EventHandler BottomButtonClick
27
{
28
add { buttomButton1.Click
+=
value; }
29
remove { buttomButton1.Click
-=
value; }
30
}
最后 重写少数几个函数就算完成了主要功能了
代码
1
protected
override
void
OnPaint(PaintEventArgs e)
2
{
3
GraphicsPath path
=
new
GraphicsPath();
4
path.AddEllipse(
new
Rectangle(Point.Empty,
this
.Size));
5
this
.Region
=
new
Region(path);
6
Graphics g
=
e.Graphics;
7
g.SmoothingMode
=
SmoothingMode.HighQuality;
8
PathGradientBrush pgb
=
new
PathGradientBrush(path);
9
if
(_state
==
ButtonSta.Up)
10
pgb.CenterColor
=
ThemeColor;
11
else
12
pgb.CenterColor
=
_downColor;
13
Color endColor
=
Color.FromArgb(
100
, ThemeColor);
14
pgb.SurroundColors
=
new
Color[] {endColor };
15
g.FillPath(pgb, path);
16
g.SmoothingMode
=
SmoothingMode.HighQuality;
17
}
18
protected
override
void
OnSizeChanged(EventArgs e)
19
{
20
base
.OnSizeChanged(e);
21
Refresh();
22
}
23
protected
override
void
OnMouseDown(MouseEventArgs e)
24
{
25
_state
=
ButtonSta.Down;
26
this
.Invalidate();
27
base
.OnMouseDown(e);
28
}
29
protected
override
void
OnMouseUp(MouseEventArgs e)
30
{
31
_state
=
ButtonSta.Up;
32
this
.Invalidate();
33
base
.OnMouseUp(e);
34
}