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 }

 

 

下载地址

你可能感兴趣的:(WPF)