上次写了一个简单的图片按钮控件,鼓足勇气发布到博客园首页,然后被移出,看来是文章质量不够。
以后先不往首页发布了,先多写几篇练练手。
本来想一步一步的来,再放个类似桌面图标的图片文本按钮控件的。
想了想,还是先把以前做的旋转按钮控件放上来吧。
这个控件类似于收音机上的旋钮,在触摸屏上用到可能性大一点,鼠标操作的话几乎没什么用处。
还是老样子,先放代码。
旋转按钮控件:
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 }