WPF程序员自定义控库系列(二)——旋转按钮

上次写了一个简单的图片按钮控件,鼓足勇气发布到博客园首页,然后被移出,看来是文章质量不够。

以后先不往首页发布了,先多写几篇练练手。

 

本来想一步一步的来,再放个类似桌面图标的图片文本按钮控件的。

想了想,还是先把以前做的旋转按钮控件放上来吧。

这个控件类似于收音机上的旋钮,在触摸屏上用到可能性大一点,鼠标操作的话几乎没什么用处。

 

还是老样子,先放代码。

旋转按钮控件:

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 }

 

 

下载地址

posted @ 2013-05-13 18:37  geeksnail  阅读(4585)  评论(1编辑  收藏  举报