C# WPF实现的语音播放自定义控件
作者:ARM830 时间:2022-11-23 19:45:49
原理很简单,利用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);
}
}
}
来源:https://www.cnblogs.com/T-ARF/p/12727925.html
标签:c#,WPF,语音播放,自定义控件
![](/images/zang.png)
![](/images/jiucuo.png)
猜你喜欢
在IDEA使用中directory和package的操作
2022-07-05 22:05:53
![](https://img.aspxhome.com/file/2023/9/79339_0s.jpg)
Unity Shader实现新手引导遮罩镂空效果
2022-08-18 16:25:12
![](https://img.aspxhome.com/file/2023/8/77228_0s.jpg)
Android实现检测手机多点触摸点数
2021-11-17 00:57:32
![](https://img.aspxhome.com/file/2023/3/117123_0s.jpg)
C语言中结构体与内存对齐实例解析
2022-05-16 12:25:18
![](https://img.aspxhome.com/file/2023/1/120801_0s.png)
C# 抽象类,抽象属性,抽象方法(实例讲解)
2022-03-14 09:22:16
![](https://img.aspxhome.com/file/2023/8/113698_0s.png)
java用户名密码验证示例代码分享
2021-10-14 08:16:14
Kotlin入门学习教程之可见性修饰符
2022-02-22 15:14:59
浅谈Mybatis传参类型如何确定
2023-11-12 12:13:21
在Winform动态启动、控制台命令行的方法
2021-11-02 05:11:07
Java注解与反射原理说明
2021-06-18 01:56:00
C#操作INI文件的辅助类IniHelper
2022-04-18 07:55:34
Activiti流程图查看实例
2022-09-10 17:51:44
Java判断字符串是否是整数或者浮点数的方法
2022-04-30 10:06:20
SpringCloud实战小贴士之Zuul的路径匹配
2021-05-26 13:26:36
Redisson RedLock红锁加锁实现过程及原理
2022-12-29 20:49:42
java线程池ThreadPoolExecutor的八种拒绝策略示例详解
2021-06-24 11:31:10
![](https://img.aspxhome.com/file/2023/0/64390_0s.png)
浅谈用java实现事件驱动机制
2022-07-12 18:06:03
C#使用DevExpress中的XtraCharts控件实现图表
2022-12-21 10:14:10
![](https://img.aspxhome.com/file/2023/7/102167_0s.png)
使用IDEA开发配置Java Web的初始化过程
2022-09-25 16:33:38
![](https://img.aspxhome.com/file/2023/4/64794_0s.jpg)
Activiti开发环境的搭建过程详解
2021-08-16 07:13:05