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 }

 

 

下載地址


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM