1,效果:
- 作用:
- 可对当前内容(例如此例中的重量信息)进行语音合成播报 。
- 可设置系统扬声器音量与状态(是否静音),同时根据扬声器状态同步更新当前控件状态与值,实现强制PC扬声器按照指定的音量进行播报,杜绝人为静音的可能。
2,引入相关程序集,命名空间。
- 程序集
微软语音合成程序集:System.Speech
第三方程序集:CoreAudioAPI(为方便使用,进行了部分修改包装)
- 命名空间:
using System.Speech.Synthesis;
using CoreAudioAPIs;
3,代码:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="112*"/>
<ColumnDefinition Width="320*"/>
<ColumnDefinition Width="85*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="59*"/>
<RowDefinition Height="51*"/>
<RowDefinition Height="77*"/>
<RowDefinition Height="43*"/>
<RowDefinition Height="32*"/>
<RowDefinition Height="58*"/>
</Grid.RowDefinitions>
<TextBlock Text="重量:" FontSize="32" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,8"></TextBlock>
<TextBox Grid.Column="1" VerticalContentAlignment="Center" x:Name="txtWeight" FontSize="30"></TextBox>
<ComboBox x:Name="combo01" Grid.Column="2" VerticalContentAlignment="Center" FontSize="32">
<ComboBoxItem FontSize="32" IsSelected="True">KG</ComboBoxItem>
<ComboBoxItem FontSize="32">T</ComboBoxItem>
<ComboBoxItem FontSize="32">G</ComboBoxItem>
</ComboBox>
<Button x:Name="btnPlay" Content="播报" FontSize="25" Grid.Row="1" Grid.Column="1" Margin="20,3" Click="btnPlay_Click"></Button>
<Grid Grid.Row="2" Grid.Column="1">
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
<RowDefinition ></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="txtStatus" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Status}" Foreground="{Binding StatusForeground}" FontSize="16"></TextBlock>
<TextBlock FontSize="24" Grid.Row="1" Text="PC扬声器设置" HorizontalAlignment="Center" VerticalAlignment="Bottom"></TextBlock>
</Grid>
<TextBlock Text="播放音量:" Grid.Row="3" FontSize="16" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,11,0,10"></TextBlock>
<Slider Grid.Row="3" Grid.Column="1" ValueChanged="slider01_ValueChanged" Minimum="0" VerticalAlignment="Center" Maximum="100" x:Name="slider01" SmallChange="1" LargeChange="5" TickPlacement="BottomRight" IsSnapToTickEnabled="True" Margin="0,11,0,10"></Slider>
<TextBlock Grid.Row="3" Grid.Column="2" FontSize="16" VerticalAlignment="Center" Margin="10,0" DockPanel.Dock="Left" Text="{Binding ElementName=slider01 ,Path=Value}"></TextBlock>
<CheckBox Grid.Row="4" x:Name="muteCheck01" Click="muteCheck01_Checked" HorizontalAlignment="Right" VerticalAlignment="Center" FontSize="16">静音</CheckBox>
</Grid>
public partial class MainWindow : Window, System.ComponentModel.INotifyPropertyChanged
{
VolumeControl volumeControl = new VolumeControl();
public event PropertyChangedEventHandler PropertyChanged;
SpeechSynthesizer speeker = new SpeechSynthesizer();
public MainWindow()
{
InitializeComponent();
volumeControl.VolumeStateChange += VolumeControl_VolumeStateChange;
slider01.Value = Volume;
muteCheck01.IsChecked = Mute;
this.DataContext = this;
Status = "准备就绪!";
StatusForeground = new SolidColorBrush(Colors.Green);
}
public bool Mute
{
get
{
return volumeControl.IsMuted;
}
set
{
volumeControl.IsMuted = value;
OnPropertyChanged(nameof(Mute));
}
}
public int Volume
{
get
{
return volumeControl.Volume;
}
set
{
volumeControl.Volume = value;
OnPropertyChanged(nameof(Volume));
}
}
string status;
public string Status
{
get
{
return status;
}
set
{
status = value;
OnPropertyChanged(nameof(Status));
}
}
Brush statusForeground = new SolidColorBrush(Colors.Black);
public Brush StatusForeground
{
set
{
statusForeground = value;
OnPropertyChanged(nameof(statusForeground));
}
get
{
return statusForeground;
}
}
private void VolumeControl_VolumeStateChange(bool mute, int volumeValue)
{
Dispatcher.Invoke(() =>
{
//移除注册,否则更新控件时将出现循环,这也是不用绑定的原因
slider01.ValueChanged -= slider01_ValueChanged;
muteCheck01.Checked -= muteCheck01_Checked;
this.muteCheck01.IsChecked = mute;
slider01.Value = volumeValue;
//重新注册
slider01.ValueChanged += slider01_ValueChanged;
muteCheck01.Checked += muteCheck01_Checked;
});
}
private void slider01_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Volume = (int)slider01.Value;
}
private void muteCheck01_Checked(object sender, RoutedEventArgs e)
{
Mute = muteCheck01.IsChecked.HasValue ? muteCheck01.IsChecked.Value : false;
}
private void btnPlay_Click(object sender, RoutedEventArgs e)
{
PromptBuilder builder = new PromptBuilder();
builder.AppendText("当前重量:", PromptVolume.Loud);
builder.AppendBreak(PromptBreak.Medium);
PromptStyle style = new PromptStyle();
style.Emphasis = PromptEmphasis.Strong;
style.Rate = PromptRate.Medium;
style.Volume = PromptVolume.ExtraLoud;
builder.StartStyle(style);
builder.AppendTextWithHint(txtWeight.Text.Trim(), SayAs.NumberCardinal);
builder.EndStyle();
string str = "";
switch (combo01.Text)
{
case "KG":
str = "千克";
break;
case "G":
str = "克";
break;
default:
str = "吨";
break;
}
builder.AppendBreak(PromptBreak.Small);
builder.AppendText(str, PromptEmphasis.Strong);
SpeechBroadcasting(builder);
}
async void SpeechBroadcasting(PromptBuilder builder)
{
Status = "播报中.....";
StatusForeground = new SolidColorBrush(Colors.Orange);
await Task.Run(() =>
{
//耗时长
speeker.Speak(builder);
}).ContinueWith(t =>
{
Dispatcher.Invoke(() =>
{
Status = "播报完成!";
StatusForeground = new SolidColorBrush(Colors.BlueViolet);
});
System.Threading.Thread.Sleep(1000);
});
Status = "准备就绪!";
StatusForeground = new SolidColorBrush(Colors.Green);
}
void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
4,Demo链接:
https://download.csdn.net/download/lingxiao16888/89298014