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

 更新时间:2021年04月07日 11:50:22   作者:ARM830  
这篇文章主要介绍了C# WPF实现的语音播放自定义控件,帮助大家更好的理解和学习使用c# WPF技术,感兴趣的朋友可以了解下

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

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

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

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

主界面xaml

<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

<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代码

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实现语音播放自定义控件的资料请关注脚本之家其它相关文章!

相关文章

  • C#操作FTP出现500错误解决办法

    C#操作FTP出现500错误解决办法

    最近在做项目的时候需要操作ftp进行文件的上传下载,但在调用using (var response = (FtpWebResponse)FtpWebRequest.GetResponse())的时候总是出现"远程服务器返回错误:(550)文件不可用(例如,未找到文件,无法访问文件)"的异常
    2014-03-03
  • C#调用CMD命令实例

    C#调用CMD命令实例

    这篇文章主要介绍了C#调用CMD命令实例本文只是给出一个比较简单的、入门级的例子,更多高级的操作技巧请参阅相关文章,需要的朋友可以参考下
    2014-08-08
  • C#编写网游客户端的实现

    C#编写网游客户端的实现

    本文主要介绍了C#编写网游客户端,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C#利用DesignSurface如何实现简单的窗体设计器

    C#利用DesignSurface如何实现简单的窗体设计器

    这篇文章主要介绍了C#利用DesignSurface如何实现简单窗体设计器的相关资料,文中通过图文及示例代码介绍的很详细,对大家具有一定的参考价值,需要的朋友们下面来一起学习学习吧。
    2017-02-02
  • Unity实现仿3D轮转图效果

    Unity实现仿3D轮转图效果

    这篇文章主要为大家详细介绍了Unity实现仿3D轮转图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • 通过C#编写一个简易的Windows截屏增强工具

    通过C#编写一个简易的Windows截屏增强工具

    在使用 Windows 系统的截屏快捷键 PrintScreen 截屏时,如果需要把截屏保存到文件,需要先粘贴到画图工具然后另存为文件。所以本文用C#编写了一个简易的Windows截屏增强工具,需要的可以参考一下
    2022-05-05
  • C#中实现查找mysql的安装路径

    C#中实现查找mysql的安装路径

    这篇文章主要介绍了C#中实现查找mysql的安装路径,本文讲解使用SQL语句查询出mysql的安装路径,方便在备份时使用,需要的朋友可以参考下
    2015-06-06
  • C# Math中常用数学运算的示例详解

    C# Math中常用数学运算的示例详解

    Math 为通用数学函数、对数函数、三角函数等提供常数和静态方法,使用起来非常方便。这篇文章主要为大家介绍几个常用的数学运算的使用,需要的可以参考一下
    2022-11-11
  • 浅谈对c# 面向对象的理解

    浅谈对c# 面向对象的理解

    这篇文章主要介绍了个人对c# 面向对象的理解,算是一个入门篇吧,给需要的小伙伴参考下,抛砖引玉。
    2014-12-12
  • c# 线程安全队列的用法原理及使用示例

    c# 线程安全队列的用法原理及使用示例

    这篇文章主要介绍了c# 线程安全队列的用法原理及使用示例,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-11-11

最新评论