上次写了一个简单的图片按钮控件,鼓足勇气发布到博客园首页,然后被移出,看来是文章质量不够。
以后先不往首页发布了,先多写几篇练练手。
本来想一步一步的来,再放个类似桌面图标的图片文本按钮控件的。
想了想,还是先把以前做的旋转按钮控件放上来吧。
这个控件类似于收音机上的旋钮,在触摸屏上用到可能性大一点,鼠标操作的话几乎没什么用处。
还是老样子,先放代码。
旋转按钮控件:
rotateButton.xaml
1 <UserControl x:Class="NingTao.rotateButton"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="200">
4 <Grid>
5 <Image Margin="0" Name="imageBtn" Stretch="Fill" RenderTransformOrigin="0.5,0.5">
6 <Image.RenderTransform>
7 <RotateTransform x:Name="rotateImage" Angle="0"/>
8 </Image.RenderTransform>
9 </Image>
10 <Label Margin="0" Name="labelBtn" HorizontalAlignment="Center" VerticalAlignment="Center" IsHitTestVisible="False"></Label>
11 <Ellipse Margin="0" Name="ellipseBtn" Fill="Black" Opacity="0.01" RenderTransformOrigin="0.5,0.5" MouseEnter="ellipseBtn_MouseEnter" MouseDown="ellipseBtn_MouseDown" MouseMove="ellipseBtn_MouseMove" MouseLeave="ellipseBtn_MouseLeave" MouseUp="ellipseBtn_MouseUp">
12 <Ellipse.RenderTransform>
13 <RotateTransform x:Name="rotateEllipse" Angle="0"/>
14 </Ellipse.RenderTransform>
15 </Ellipse>
16 </Grid>
17 </UserControl>
rotateButton.xaml.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14
15 namespace NingTao
16 {
17 /// <summary>
18 /// rotateButton.xaml 的交互逻辑
19 /// </summary>
20 public partial class rotateButton : UserControl
21 {
22 // 设置按钮使能状态
23 private bool isEnable = true;
24 // 按钮的4种状态图片
25 private ImageSource imageUp = null;
26 private ImageSource imageHover = null;
27 private ImageSource imageDown = null;
28 private ImageSource imageDisable = null;
29 // 按钮的文本属性
30 private FontFamily textFamily;
31 private double textSize;
32 private Brush textColor;
33 // 按钮数值
34 private int btnValue = 0;
35 // 最小最大值
36 private int valueMin = 0;
37 private int valueMax = 100;
38 // 角度单位 每单位数值表示角度 可转动(valueMax*anglePerValue/360)圈
39 private int anglePerValue = 18;
40 // 累积旋转角度 小于刻度时不断累积
41 private double angleDelta = 0;
42 // 是否在当前按钮中按下
43 private bool isMouseDown = false;
44 // 数值改变事件
45 public event EventHandler valueChange;
46
47 public rotateButton()
48 {
49 InitializeComponent();
50 }
51
52 #region 属性赋值
53 // 按钮可用
54 public bool IsEnable
55 {
56 get { return isEnable; }
57 set
58 {
59 isEnable = value;
60 imageBtn.Source = isEnable ? imageUp : imageDisable;
61 }
62 }
63 // 按钮弹起图片
64 public ImageSource ImageUp
65 {
66 get { return imageUp; }
67 set
68 {
69 imageUp = value;
70 imageBtn.Source = imageUp;
71 }
72 }
73 // 按钮划过图片
74 public ImageSource ImageHover
75 {
76 get { return imageHover; }
77 set { imageHover = value; }
78 }
79 // 按钮按下图片
80 public ImageSource ImageDown
81 {
82 get { return imageDown; }
83 set { imageDown = value; }
84 }
85 // 按钮禁用图片
86 public ImageSource ImageDisable
87 {
88 get { return imageDisable; }
89 set { imageDisable = value; }
90 }
91 // 按钮字体
92 public FontFamily TextFamily
93 {
94 get { return textFamily; }
95 set
96 {
97 textFamily = value;
98 labelBtn.FontFamily = textFamily;
99 }
100 }
101 // 按钮字号
102 public double TextSize
103 {
104 get { return textSize; }
105 set
106 {
107 textSize = value;
108 labelBtn.FontSize = textSize;
109 }
110 }
111 // 文字颜色
112 public Brush TextColor
113 {
114 get { return textColor; }
115 set
116 {
117 textColor = value;
118 labelBtn.Foreground = textColor;
119 }
120 }
121 // 按钮数值
122 public int Value
123 {
124 get { return btnValue; }
125 set
126 {
127 if ((value > ValueMin) && (value < ValueMax))
128 {
129 btnValue = value;
130 // 图像对齐
131 valueReNew();
132 }
133 }
134 }
135 // 最小值
136 public int ValueMin
137 {
138 get { return valueMin; }
139 set { valueMin = value; }
140 }
141 // 最大值
142 public int ValueMax
143 {
144 get { return valueMax; }
145 set { valueMax = value; }
146 }
147 // 角度单位
148 public int AnglePerValue
149 {
150 get { return anglePerValue; }
151 set { anglePerValue = value; }
152 }
153 #endregion
154
155 #region 按钮事件
156 // 进入
157 private void ellipseBtn_MouseEnter(object sender, MouseEventArgs e)
158 {
159 if (isEnable)
160 {
161 if (null != imageHover)
162 {
163 imageBtn.Source = imageHover;
164 }
165 }
166 }
167 // 按下
168 private void ellipseBtn_MouseDown(object sender, MouseButtonEventArgs e)
169 {
170 if (isEnable)
171 {
172 isMouseDown = true;
173 if (null != imageDown)
174 {
175 imageBtn.Source = imageDown;
176 // 重新设置旋转中心点
177 //rotateImage.CenterX = imageBtn.ActualWidth / 2;
178 //rotateImage.CenterY = imageBtn.ActualHeight / 2;
179 //rotateEllipse.CenterX = ellipseBtn.ActualWidth / 2;
180 //rotateEllipse.CenterY = ellipseBtn.ActualHeight / 2;
181 // 圆形旋转对齐
182 Point P = e.GetPosition(sender as IInputElement);
183 //double angle = Math.Atan2(P.Y - rotateEllipse.CenterY, P.X - rotateEllipse.CenterX) * 180 / Math.PI;
184 double angle = Math.Atan2(P.Y - (ellipseBtn.ActualHeight / 2), P.X - (ellipseBtn.ActualWidth / 2)) * 180 / Math.PI;
185 rotateEllipse.Angle = angle;
186 // 图像对齐
187 valueReNew();
188 }
189 }
190 }
191 // 移动
192 private void ellipseBtn_MouseMove(object sender, MouseEventArgs e)
193 {
194 if (isEnable)
195 {
196 //鼠标已按下
197 if (isMouseDown)
198 {
199 // 计算旋转角度
200 Point P = e.GetPosition(sender as IInputElement);
201 //double angle = Math.Atan2(P.Y - rotateEllipse.CenterY, P.X - rotateEllipse.CenterX) * 180 / Math.PI;
202 double angle = Math.Atan2(P.Y - (ellipseBtn.ActualHeight / 2), P.X - (ellipseBtn.ActualWidth / 2)) * 180 / Math.PI;
203 // 加上累积角度
204 angle += angleDelta;
205 // 大于一格的刻度
206 if (Math.Abs(angle) > anglePerValue)
207 {
208 // 与单元角度整除的数 作为数值和旋转的增量
209 int angleGrid = (int)angle / anglePerValue;
210 // 当前数值不超过最大最小值
211 int currentValue = angleGrid + btnValue;
212 if (currentValue < valueMin) { currentValue = valueMin; }
213 if (currentValue > ValueMax) { currentValue = ValueMax; }
214 // 更新数值
215 btnValue = currentValue;
216 // 触发数值更新事件
217 if (null != valueChange) { valueChange(this, null); }
218 // 圆形旋转对齐
219 rotateEllipse.Angle += anglePerValue * angleGrid;
220 // 余数作为新的累积角度
221 angle = angle % anglePerValue;
222 }
223 // 保存累积角度
224 angleDelta = angle;
225 // 图像对齐
226 valueReNew();
227 }
228 }
229 }
230 // 弹起
231 private void ellipseBtn_MouseUp(object sender, MouseButtonEventArgs e)
232 {
233 if (isEnable)
234 {
235 // 完成在控件上点击
236 if (isMouseDown)
237 {
238 isMouseDown = false;
239 imageBtn.Source = imageUp;
240 // 清空累积值
241 angleDelta = 0;
242 // 图像对齐
243 valueReNew();
244 }
245 }
246 }
247 // 离开
248 private void ellipseBtn_MouseLeave(object sender, MouseEventArgs e)
249 {
250 if (isEnable)
251 {
252 isMouseDown = false;
253 imageBtn.Source = imageUp;
254 // 清空累积值
255 angleDelta = 0;
256 // 图像对齐
257 valueReNew();
258 }
259 }
260 #endregion
261
262 // 图像对齐
263 private void valueReNew()
264 {
265 // 显示数值
266 labelBtn.Content = btnValue.ToString();
267 // 计算旋转角度
268 //double angle = (anglePerValue * btnValue) + angleDelta;
269 double angle = (anglePerValue * btnValue);
270 // 旋转图片
271 rotateImage.Angle = angle;
272 }
273 }
274 }
演示窗体:
这里用了一个音量调节类来实现旋转第2个按钮来调节音量,需引用CoreAudioApi.dll。
Window1.xaml
1 <Window x:Class="ntCtrlLibs.Window1"
2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4 xmlns:rotateButton="clr-namespace:NingTao;assembly=rotateButton"
5 Title="WPF控件测试" Height="300" Width="600" Loaded="Window_Loaded">
6 <Grid>
7 <rotateButton:rotateButton x:Name="rotateButtonT" Margin="12,12,0,0" Width="150" Height="150" HorizontalAlignment="Left" VerticalAlignment="Top"></rotateButton:rotateButton>
8 <rotateButton:rotateButton x:Name="rotateButtonN" Margin="170,12,0,0" Width="150" Height="150" HorizontalAlignment="Left" VerticalAlignment="Top"></rotateButton:rotateButton>
9 </Grid>
10 </Window>
Window1.xaml.cs(图片动态加载,可在调用控件时置顶背景图片)
1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Windows;
6 using System.Windows.Controls;
7 using System.Windows.Data;
8 using System.Windows.Documents;
9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14
15 namespace ntCtrlLibs
16 {
17 /// <summary>
18 /// Window1.xaml 的交互逻辑
19 /// </summary>
20 public partial class Window1 : Window
21 {
22 // 当前声音设备
23 private CoreAudioApi.MMDevice defaultDevice = null;
24
25 public Window1()
26 {
27 InitializeComponent();
28 }
29
30 private void Window_Loaded(object sender, RoutedEventArgs e)
31 {
32 // ================ 旋转按钮 ================
33 try
34 {
35 rotateButtonT.ImageUp = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\volume1.jpg"));
36 rotateButtonT.ImageDown = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\volume2.jpg"));
37 rotateButtonN.ImageUp = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\btn1.png"));
38 rotateButtonN.ImageDown = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\btn2.png"));
39 }
40 catch
41 {
42 MessageBox.Show("旋转按钮图片加载出错!");
43 }
44 rotateButtonT.Value = 50;
45 rotateButtonT.TextSize = 20;
46 rotateButtonT.TextColor = new SolidColorBrush(Colors.Blue);
47
48 rotateButtonN.TextSize = 20;
49 rotateButtonN.TextColor = new SolidColorBrush(Colors.Blue);
50 // 获取声音设备
51 CoreAudioApi.MMDeviceEnumerator devEnum = new CoreAudioApi.MMDeviceEnumerator();
52 try
53 {
54 defaultDevice = devEnum.GetDefaultAudioEndpoint(CoreAudioApi.EDataFlow.eRender, CoreAudioApi.ERole.eMultimedia);
55 }
56 catch
57 {
58 }
59 if (null != defaultDevice)
60 {
61 // 初始化数值
62 rotateButtonN.Value = (int)(100 * defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar);
63 // 按钮数值改变
64 rotateButtonN.valueChange += (btnSender, btnEvent) =>
65 {
66 // 调节音量
67 defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar = ((float)rotateButtonN.Value / 100);
68 };
69 }
70 }
71 }
72 }