zoukankan      html  css  js  c++  java
  • WPF程序员自定义控库系列(三)——冷却按钮

    最近新做了一个倒计时按钮,感觉跟游戏里的技能冷却图标挺像的。

    整理了一下,先上demo。

    下载地址

    主要用了控件的裁剪功能。

    控件的XAML

    其中,文本控件是用来显示倒计时用的。冷却按钮里面没有,所以隐藏掉了。

     1 <UserControl x:Class="NingTao.coolDownButton"
     2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
     4   <Grid>
     5 
     6     <Image Margin="0" Name="imageBtnBack" MouseUp="imageBtnBack_MouseUp"></Image>
     7     <Image Margin="0" Name="imageBtnFront" IsHitTestVisible="False"></Image>
     8     <Label Margin="0,0,0,0" Name="labelCounter" IsHitTestVisible="False" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Foreground="Red" FontSize="26" Visibility="Hidden">0</Label>
     9 
    10   </Grid>
    11 </UserControl>

    控件的CS文件

    其中,把以前的检测无动作功能去掉,以前是有动作就从新计时。

    注释掉的部分是反方向旋转的,因为跟常见的冷却方向不一致,所以更改方向。

    虽然代码不是很多,可是考虑cos和sin的时候也挺费工夫的。

    弧线的起点和终点不一样,弧线的圆心在哪一侧也是不一样的。

      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 using System.Runtime.InteropServices;
     15 
     16 namespace NingTao
     17 {
     18   /// <summary>
     19   /// UserControl1.xaml 的交互逻辑
     20   /// </summary>
     21   public partial class coolDownButton : UserControl
     22   {
     23     // 按钮的背景前景图片
     24     private ImageSource imageBack = null;
     25     private ImageSource imageFront = null;
     26     // 文本属性
     27     private FontFamily textFamily;
     28     private double textSize;
     29     private Brush textColor;
     30     // 显示倒计时的计时器
     31     private System.Timers.Timer msgTimer = new System.Timers.Timer();
     32     // 计时器到期委托调用
     33     private delegate void invokeTimerTrick();
     34     // 倒计时最大值
     35     private double maxCounter = 0;
     36     // 无动作时间
     37     private double nowCounter = 0;
     38     // 点击事件 或者倒计时结束触发
     39     public event EventHandler Click = null;
     40     // 是否由点击触发(可能为页面后退事件)
     41     public bool isClickEvent = false;
     42 
     43     // 按钮背景图片
     44     public ImageSource ImageBack
     45     {
     46       get { return imageBack; }
     47       set
     48       {
     49         imageBack = value;
     50         imageBtnBack.Source = imageBack;
     51       }
     52     }
     53     // 按钮前景图片
     54     public ImageSource ImageFront
     55     {
     56       get { return imageFront; }
     57       set
     58       {
     59         imageFront = value;
     60         imageBtnFront.Source = imageFront;
     61       }
     62     }
     63     // 文本字体
     64     public FontFamily TextFamily
     65     {
     66       get { return textFamily; }
     67       set
     68       {
     69         textFamily = value;
     70         labelCounter.FontFamily = textFamily;
     71       }
     72     }
     73     // 文本字号
     74     public double TextSize
     75     {
     76       get { return textSize; }
     77       set
     78       {
     79         textSize = value;
     80         labelCounter.FontSize = textSize;
     81       }
     82     }
     83     // 文本颜色
     84     public Brush TextColor
     85     {
     86       get { return textColor; }
     87       set
     88       {
     89         textColor = value;
     90         labelCounter.Foreground = textColor;
     91       }
     92     }
     93     // 倒计时最大值
     94     public double MaxCounter
     95     {
     96       get { return maxCounter; }
     97       set
     98       {
     99         nowCounter = 0;
    100         maxCounter = value;
    101         // 启动计时器
    102         msgTimer.Start();
    103       }
    104     }
    105 
    106     public coolDownButton()
    107     {
    108       InitializeComponent();
    109 
    110       // 初始化海报倒计时计数器
    111       msgTimer.Elapsed += new System.Timers.ElapsedEventHandler(msgTimer_Elapsed);
    112       msgTimer.Interval = 200;
    113     }
    114 
    115     // 计数器到期
    116     private void msgTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    117     {
    118       //nowCounter = GetIdleTick() / 1000;
    119       nowCounter += 0.2;
    120       if (nowCounter < maxCounter + 0.2)
    121       {
    122         Dispatcher.Invoke(new invokeTimerTrick(reDraw));
    123       }
    124       else
    125       {
    126         isClickEvent = false;
    127         Dispatcher.Invoke(new invokeTimerTrick(buttonClick));
    128       }
    129     }
    130 
    131     private void reDraw()
    132     {
    133       // 显示剩余时间
    134       int timeLeft = Convert.ToInt32(maxCounter - nowCounter);
    135       int intMinute = timeLeft / 60;
    136       int intSecond = timeLeft % 60;
    137       labelCounter.Content = string.Format("{0:D2}:{1:D2}",intMinute, intSecond);
    138       // 裁剪剩余时间扇形区域
    139       double angle = 360 - 360 * nowCounter / maxCounter;
    140       if (360 == angle)
    141       {
    142         imageBtnFront.Clip = new EllipseGeometry(new Rect(0, 0, imageBtnFront.ActualWidth, imageBtnFront.ActualHeight));
    143       }
    144       else
    145       {
    146         //PathGeometry PathGeometry1 = new PathGeometry();
    147         //PathFigure PathFigure1 = new PathFigure();
    148         //PathFigure1.StartPoint = new Point(imageBtnFront.ActualWidth / 2, imageBtnFront.ActualHeight / 2);
    149         //LineSegment LineSegment1 = new LineSegment();
    150         //LineSegment1.Point = new Point(imageBtnFront.ActualWidth / 2, 0);
    151         //PathFigure1.Segments.Add(LineSegment1);
    152         //double offsetX = Math.Sin(angle * Math.PI / 180);
    153         //double offsetY = Math.Cos(angle * Math.PI / 180);
    154         //Point endPoint = new Point(imageBtnFront.ActualWidth * (1 + offsetX) / 2, imageBtnFront.ActualHeight * (1 - offsetY) / 2);
    155         //ArcSegment ArcSegment1 = new ArcSegment(
    156         //  endPoint,
    157         //  new Size(imageBtnFront.ActualWidth / 2, imageBtnFront.ActualHeight / 2),
    158         //  angle,
    159         //  (angle > 180),
    160         //  SweepDirection.Clockwise,
    161         //  true);
    162         //PathFigure1.Segments.Add(ArcSegment1);
    163         //PathGeometry1.Figures.Add(PathFigure1);
    164         //imageBtnFront.Clip = PathGeometry1;
    165         // 顺时针
    166         PathGeometry PathGeometry1 = new PathGeometry();
    167         PathFigure PathFigure1 = new PathFigure();
    168         // 起点为中心点
    169         PathFigure1.StartPoint = new Point(imageBtnFront.ActualWidth / 2, imageBtnFront.ActualHeight / 2);
    170         // 连接到扇形的圆弧起点
    171         LineSegment LineSegment1 = new LineSegment();
    172         double offsetX = Math.Sin(angle * Math.PI / 180);
    173         double offsetY = Math.Cos(angle * Math.PI / 180);
    174         LineSegment1.Point = new Point(imageBtnFront.ActualWidth * (1 - offsetX) / 2, imageBtnFront.ActualHeight * (1 - offsetY) / 2);
    175         PathFigure1.Segments.Add(LineSegment1);
    176         // 圆弧 终点在正上方
    177         ArcSegment ArcSegment1 = new ArcSegment(
    178           new Point(imageBtnFront.ActualWidth / 2, 0),
    179           new Size(imageBtnFront.ActualWidth / 2, imageBtnFront.ActualHeight / 2),
    180           angle,
    181           (angle > 180),
    182           SweepDirection.Clockwise,
    183           true);
    184         PathFigure1.Segments.Add(ArcSegment1);
    185         // 对图像控件进行裁剪
    186         PathGeometry1.Figures.Add(PathFigure1);
    187         imageBtnFront.Clip = PathGeometry1;
    188       }
    189     }
    190 
    191     // 点击事件
    192     private void imageBtnBack_MouseUp(object sender, MouseButtonEventArgs e)
    193     {
    194       isClickEvent = true;
    195       buttonClick();
    196     }
    197 
    198     private void buttonClick()
    199     {
    200       // 停止计时器
    201       msgTimer.Stop();
    202       // 触发点击事件
    203       if (null != Click) Click(null, null);
    204     }
    205 
    206     public void stopCount()
    207     {
    208       // 停止计时器
    209       msgTimer.Stop();
    210     }
    211 
    212     [DllImport("user32.dll")]
    213     static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
    214 
    215     /// <summary>
    216     /// 获取最后一次输入经过的时间
    217     /// </summary>
    218     /// <returns></returns>
    219     private int GetIdleTick()
    220     {
    221       LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
    222       lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
    223       if (!GetLastInputInfo(ref lastInputInfo)) return 0;
    224       return Environment.TickCount - (int)lastInputInfo.dwTime;
    225     }
    226 
    227     [StructLayout(LayoutKind.Sequential)]
    228     private struct LASTINPUTINFO
    229     {
    230       [MarshalAs(UnmanagedType.U4)]
    231       public int cbSize;
    232       [MarshalAs(UnmanagedType.U4)]
    233       public uint dwTime;
    234     }
    235   }
    236 }

    调用:

    先添加引用coolDownButton.dll。

    前边是xaml里的调用部分,后边是动态加载图片和设置点击事件。

     1 // xaml
     2 // xmlns:coolDownButton="clr-namespace:NingTao;assembly=coolDownButton"
     3 //<coolDownButton:coolDownButton x:Name="cdButton" HorizontalAlignment="Right" Width="200" Margin="0,12,12,50"></coolDownButton:coolDownButton>
     4 
     5       // ================ 冷却按钮 ================
     6       cdButton.ImageBack = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\a1.png"));
     7       cdButton.ImageFront = new BitmapImage(new Uri(System.Environment.CurrentDirectory + "\\skins\\a2.png"));
     8       cdButton.Click += new EventHandler(cdButton_Click);
     9 
    10     void cdButton_Click(object sender, EventArgs e)
    11     {
    12       // 按钮被点击
    13       if (cdButton.isClickEvent)
    14       {
    15         cdButton.MaxCounter = Convert.ToDouble(textBox1.Text);
    16       }
    17       else
    18       {
    19         MessageBox.Show("冷却完成");
    20       }
    21     }
  • 相关阅读:
    node.js基础回顾
    PHP基础回顾之表单(二)
    PHP基础回顾(一)
    知识图谱Knowledge Graph
    Qt addStretch()详解
    Qt实现 QQ好友列表QToolBox
    Qt5
    用户级线程和内核级线程
    TCP状态转换图、滑动窗口、半连接状态、2MSL
    理解tcp顺序释放操作和tcp的半关闭
  • 原文地址:https://www.cnblogs.com/slowhand/p/3095297.html
Copyright © 2011-2022 走看看