服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# WPF实现的语音播放自定义控件

C# WPF实现的语音播放自定义控件

2022-11-10 14:00ARM830 C#

这篇文章主要介绍了C# WPF实现的语音播放自定义控件,帮助大家更好的理解和学习使用c# WPF技术,感兴趣的朋友可以了解下

原理很简单,利用Path画一个图,然后用动画进行播放,播放时间由依赖属性输入赋值与控件内部维护的一个计时器进行控制。

控件基本是玩具,无法作为真实项目使用。

因为没有设置播放源,所以编写异步播放源或者实际播放时候要将事件引发,是否播放等属性,事件移到真实播放事件

非专业UI,即使知道怎么画图也是画的不如意,到底是眼睛会了,手不行啊。

C# WPF实现的语音播放自定义控件

主界面xaml

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<local:VoiceAnimeButton  Height="40" Width="200" IconMargin="5,0,-8,0" HorizontalContentAlignment="Center" CornerRadius="15" VerticalContentAlignment="Center" BorderBrush="Black" IconFill="Black"  BorderThickness="1" Background="Transparent"  VoicePlayTime="0:0:1" >
      <local:VoiceAnimeButton.ContentTemplate>
        <DataTemplate>
          <TextBlock FontSize="10" >
           <Run Text="播放时间"/>
           <Run Text="{Binding RelativeSource={RelativeSource AncestorLevel=1,AncestorType=local:VoiceAnimeButton,Mode=FindAncestor}, Path=VoicePlayTime}"/>
           <Run Text=" "/>
           <Run Text="状态: "/>
           <Run Text="{Binding RelativeSource={RelativeSource AncestorLevel=1,AncestorType=local:VoiceAnimeButton,Mode=FindAncestor}, Path=IsVoicePlay}"/>
          </TextBlock>
        </DataTemplate>
      </local:VoiceAnimeButton.ContentTemplate>
    </local:VoiceAnimeButton>

控件设计XAML

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<ResourceDictionary
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="clr-namespace:声音播放动画">
 
 
  <Style TargetType="{x:Type local:VoiceAnimeButton}">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type local:VoiceAnimeButton}">
          <Border Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="{TemplateBinding CornerRadius}" Padding="1">
            <Grid >
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto"/>
                <ColumnDefinition Width="*"/>
              </Grid.ColumnDefinitions>
              <Border Margin="{TemplateBinding IconMargin}" >
                <Viewbox>
                  <Path x:Name="VoicePath" Height="{TemplateBinding IconHieght}" Width="{TemplateBinding IconWidth}"  Fill="{TemplateBinding IconFill}" >
                    <Path.Data>
                      <PathGeometry>
                        <PathFigureCollection>
                          M20 20 Q12 45 20 85 l7 -4 Q18 48 27 23 l-7 -3Z
                  M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                  M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                  M58 41 Q55 49 58 61 l17 -11Z
                        </PathFigureCollection>
                      </PathGeometry>
                    </Path.Data>
                  </Path>
                </Viewbox>
              </Border>
              <ContentPresenter Grid.Column="1"  HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
            </Grid>
          </Border>
          <ControlTemplate.Triggers>
            <EventTrigger RoutedEvent="VoicePlayStart">
              <BeginStoryboard x:Name="bs1">
                <Storyboard Storyboard.TargetProperty="Data" Storyboard.TargetName="VoicePath" RepeatBehavior="Forever" Duration="0:0:0.4" BeginTime="0">
                  <ObjectAnimationUsingKeyFrames>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                      <DiscreteObjectKeyFrame.Value>
                        <PathGeometry>
                          <PathFigureCollection>
                            M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                            M58 41 Q55 49 58 61 l17 -11Z
                          </PathFigureCollection>
                        </PathGeometry>
                      </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.2">
                      <DiscreteObjectKeyFrame.Value>
                        <PathGeometry>
                          <PathFigureCollection>
                            M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                            M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                            M58 41 Q55 49 58 61 l17 -11Z
                          </PathFigureCollection>
                        </PathGeometry>
                      </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                    <DiscreteObjectKeyFrame KeyTime="0:0:0.3">
                      <DiscreteObjectKeyFrame.Value>
                        <PathGeometry>
                          <PathFigureCollection>
                            M20 20 Q12 45 20 85 l7 -4 Q18 48 27 23 l-7 -3Z
                            M32 29 Q22 45 32 75 l7 -4 Q29 50 38 33 l-6.5 -4
                            M45 35 Q38 48 45 68 l7 -4 Q45 50 52 39 l-7.5 -4
                            M58 41 Q55 49 58 61 l17 -11Z
                          </PathFigureCollection>
                        </PathGeometry>
                      </DiscreteObjectKeyFrame.Value>
                    </DiscreteObjectKeyFrame>
                  </ObjectAnimationUsingKeyFrames>
 
                </Storyboard>
              </BeginStoryboard>
            </EventTrigger>
            <EventTrigger RoutedEvent="VoicePlayEnd">
              <RemoveStoryboard BeginStoryboardName="bs1"/>
            </EventTrigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

控件CS代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
 
namespace 声音播放动画
{
  
  public class VoiceAnimeButton : ContentControl
  {
    static VoiceAnimeButton()
    {
      DefaultStyleKeyProperty.OverrideMetadata(typeof(VoiceAnimeButton), new FrameworkPropertyMetadata(typeof(VoiceAnimeButton)));
    }
 
    private DispatcherTimer Timer;
 
    public VoiceAnimeButton()
    {
      Timer = new DispatcherTimer();
      Timer.Tick += Timer_Tick;
      Timer.Interval = TimeSpan.FromSeconds(1);
    }
 
    private void Timer_Tick(object sender, EventArgs e)
    {
      Timer.Stop();
      IsVoicePlay = false;
      this.RaiseEvent(new RoutedEventArgs(VoicePlayEndEvent, this));
 
    }
 
    public static readonly RoutedEvent VoicePlayStartEvent = EventManager.RegisterRoutedEvent("VoicePlayStart", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(VoiceAnimeButton));
 
    /// <summary>
    /// 声音播放开始事件
    /// </summary>
    public event RoutedEventHandler VoicePlayStart
    {
      add
      {
        this.AddHandler(VoicePlayStartEvent, value);
      }
      remove
      {
        RemoveHandler(VoicePlayStartEvent, value);
      }
    }
 
 
    public static readonly RoutedEvent VoicePlayEndEvent= EventManager.RegisterRoutedEvent("VoicePlayEnd", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(VoiceAnimeButton));
 
    /// <summary>
    /// 声音播放结束事件
    /// </summary>
    public event RoutedEventHandler VoicePlayEnd
    {
      add
      {
        AddHandler(VoicePlayEndEvent, value);
      }
      remove
      {
        RemoveHandler(VoicePlayEndEvent, value);
      }
    }
 
    protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
    {
      base.OnMouseLeftButtonDown(e);
      IsMouseLeftClick = true;
      Timer.Interval = VoicePlayTime;
      Timer.Start();
      IsVoicePlay = true;
      this.RaiseEvent(new RoutedEventArgs(VoicePlayStartEvent,this));
      
    }
    protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
    {
      base.OnMouseLeftButtonUp(e);
      IsMouseLeftClick = false;
    }
 
    public static readonly DependencyProperty VoicePlayTimeProperty = DependencyProperty.Register("VoicePlayTime", typeof(TimeSpan), typeof(VoiceAnimeButton), new PropertyMetadata(TimeSpan.FromMilliseconds(1000)));
   
    public TimeSpan VoicePlayTime
    {
      get => (TimeSpan)GetValue(VoicePlayTimeProperty);
      set => SetValue(VoicePlayTimeProperty, value);
    }
    public static readonly DependencyProperty IsMouseLeftClickProperty = DependencyProperty.Register("IsMouseLeftClick", typeof(bool), typeof(VoiceAnimeButton),new PropertyMetadata(false));
 
    public bool IsMouseLeftClick
    {
      get => (bool)GetValue(IsMouseLeftClickProperty);
      set => SetValue(IsMouseLeftClickProperty, value);
    }
    public static readonly DependencyProperty IconWidthProperty = DependencyProperty.Register("IconWidth", typeof(double), typeof(VoiceAnimeButton), new PropertyMetadata(100.0));
 
    public double IconWidth
    {
      get => Convert.ToDouble(IconWidthProperty);
      set => SetValue(IconWidthProperty, value);
    }
    public static readonly DependencyProperty IconHieghtProperty = DependencyProperty.Register("IconHieght", typeof(double), typeof(VoiceAnimeButton), new PropertyMetadata(100.0));
 
    public double IconHieght
    {
      get => Convert.ToDouble(IconHieghtProperty);
      set => SetValue(IconHieghtProperty, value);
    }
 
    public static readonly DependencyProperty IconFillProperty= DependencyProperty.Register("IconFill", typeof(SolidColorBrush), typeof(VoiceAnimeButton), new PropertyMetadata(new SolidColorBrush(Colors.Black)));
 
    public SolidColorBrush IconFill
    {
      get => GetValue(IconFillProperty) as SolidColorBrush;
      set => SetValue(IconFillProperty, value);
    }
 
    public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(VoiceAnimeButton), new PropertyMetadata(new CornerRadius(0)));
 
    public CornerRadius CornerRadius
    {
      get => (CornerRadius)GetValue(CornerRadiusProperty);
      set => SetValue(CornerRadiusProperty, value);
    }
    public static readonly DependencyProperty IconMarginProperty = DependencyProperty.Register("IconMargin", typeof(Thickness), typeof(VoiceAnimeButton), new PropertyMetadata(new Thickness(0.0)));
 
    public Thickness IconMargin
    {
      get => (Thickness)GetValue(IconMarginProperty);
      set => SetValue(IconMarginProperty, value);
    }
 
    public static readonly DependencyProperty IsVoicePlayProperty = DependencyProperty.Register("IsVoicePlay", typeof(bool), typeof(VoiceAnimeButton));
 
    public bool IsVoicePlay
    {
      get => (bool)GetValue(IsVoicePlayProperty);
      set => SetValue(IsVoicePlayProperty, value);
    }
  }
}

以上就是C# WPF实现的语音播放自定义控件的详细内容,更多关于WPF实现语音播放自定义控件的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/T-ARF/p/12727925.html

延伸 · 阅读

精彩推荐
  • C#winform实现关闭按钮失效的两种方法

    winform实现关闭按钮失效的两种方法

    这篇文章主要介绍了winform实现关闭按钮失效的两种方法,实例分析了WinForm实现关闭按钮失效的原理与所涉及的相关技巧,需要的朋友可以参考下...

    我心依旧7862021-10-25
  • C#C#学习笔记整理_浅谈Math类的方法

    C#学习笔记整理_浅谈Math类的方法

    下面小编就为大家带来一篇C#学习笔记整理_浅谈Math类的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看...

    C#教程网5852021-12-07
  • C#C#中for循环、while循环循环执行的方法

    C#中for循环、while循环循环执行的方法

    这篇文章主要介绍了C#中for循环、while循环循环执行的方法的相关资料,非常不错,具有参考借鉴价值,感兴趣的朋友一起学习吧...

    C#教程网6162021-11-29
  • C#C# XML中的转义字符操作

    C# XML中的转义字符操作

    这篇文章主要介绍了C# XML中的转义字符操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    长得帅性格好技术屌11732022-10-27
  • C#C#使用Unity实现剪刀石头布游戏

    C#使用Unity实现剪刀石头布游戏

    这篇文章主要为大家详细介绍了C#语言使用Unity实现剪刀石头布游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    莹莹carriex4722022-03-08
  • C#c#获取图片正确格式的方法

    c#获取图片正确格式的方法

    这篇文章主要介绍了c#获取图片正确格式的方法,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...

    Soar、毅5762022-09-22
  • C#C#在LINQ中使用GroupBy

    C#在LINQ中使用GroupBy

    这篇文章主要介绍了C#在LINQ中如何使用GroupBy,帮助大家更好的理解和学习c#,感兴趣的朋友可以了解下...

    cnxy4782022-10-07
  • C#C#结束Excel进程的步骤教学

    C#结束Excel进程的步骤教学

    在本篇文章里小编给大家分享了关于C#结束Excel进程的步骤教学内容,有兴趣的朋友们学习下。...

    C#教程网10272022-03-08