制作播放器控制按钮组合控件 GDI+绘制
制作一个播放器的控制按钮组合控件 较好的封装子控件 并提供公开属性更换外观
组合控件还差按钮上的图形 比如中间的播放图标 上一个 下一个 打开 停止的图标,控件使用alpha混合和渐变
组合控件一共上下左右四个按钮 自身作为中间的按钮使用,并且可以适应各种宽度和高度
我的思路是这样的:总共有五个类 组合控件MP3Buttons 上下左右四个按钮类 ,主要实现一个周边按钮 其它3个按钮继承自这个按钮,并重写一个方法就可以了,所以主要是实现2个类 组合按钮类,任意一个周边按钮
1.先设计一个左边按钮的类 LeftButton:UserControl 本可以继承Control类 不过Control不支持背景透明 UserControl支持背景透明,在Resize事件中限制控件的区域
2.创建RightButton TopButton BottomButton 它们继承自LeftButton
3.创建MP3Buttons组合控件 继承自UserControl 设计对外属性以更改控件的外观 设计各按钮的单击事件
一.LeftButton的实现
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个按钮 只需要重写一个方法以更改有效区域
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 }
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 }
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.设计辅助类型和字段
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个属性 一个用于更改自身的外观 一个用于更改周边按钮的外观,这样可以形成外观组合 获得更丰富的外观
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
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 }
最后 重写少数几个函数就算完成了主要功能了
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 }