zoukankan      html  css  js  c++  java
  • 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 }

    下载地址

  • 相关阅读:
    3.约束及修改数据表
    RSA总结
    消息队列面试官爱问的问题(一)
    Maven模块化开发
    系统初始化脚本和检查初始化结果脚本(centos7)
    kubectl 命令自动补全
    Kubernetes1.13.1部署Kuberneted-dashboard v1.10.1
    python实现连接MySQL、Redis并获取数据
    shell 脚本实现退点输出
    理论经典:TCP协议的3次握手与4次挥手过程详解
  • 原文地址:https://www.cnblogs.com/slowhand/p/3076259.html
Copyright © 2011-2022 走看看