WPF开发txt阅读器11:自定义控件更改音量语速

news2024/11/16 12:03:27

文章目录

    • 自定义控件
    • 控件调用
    • 自定义事件
    • 更改音量和语速

txt阅读器系列:

  • 需求分析和文件读写
  • 目录提取类💎列表控件与目录
  • 字体控件绑定💎前景/背景颜色
  • 书籍管理系统💎用树形图管理书籍
  • 语音播放💎播放进度显示💎快进快退💎语速音量

自定义控件

音量和语速都可以用数值来表示,这一点与之前的字体大小就十分相似,故其xml代码也设置为Slider+-号相结合。

换言之,阅读设置中的文字大小,朗读设置中的阅读速度和阅读音量,从控件的角度来说是完全雷同的。为了提高代码的复用率,最好能够把这些TextBox, Slider, Button等控件打包在一起,形成一个新的控件。

方法也很简单,右键TxtReader,添加用户控件,命名为AdvanceSlider,其xaml代码为

<DockPanel LastChildFill="True">
    <TextBlock Text="{Binding Title}" Width="30" VerticalAlignment="Center"/>
    <TextBox Width="50" Height="20" Text="{Binding Value, ElementName=slider}"/>
    <Button Content="-" Width="20" Click="btnChange_Click"/>
    <Button Content="+" Width="20" DockPanel.Dock="Right" Click="btnChange_Click"/>
    <Slider x:Name="slider" VerticalAlignment="Center" Width="150" 
        Minimum="{Binding Min}" Maximum="{Binding Max}" 
        Value="{Binding Value}" IsSnapToTickEnabled="True"/>
</DockPanel>

C#代码为

public partial class AdvanceSlider : UserControl
{
    public AdvanceSlider()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    public double Min { set; get; }
    public double Max { set; get; }
    public double Value { set; get; }
    public string Title { set; get; }

    private void btnChange_Click(object sender, RoutedEventArgs e)
    {
        var btn = sender as Button;
        slider.Value += btn.Content.ToString() == "+" ? 1 : -1;
    }
}

其中,this.DataContext=this,可方便xaml中绑定控件属性,使得后面定义的Min, Max, Value, Title在引用时可以设置。

btnChange_Click表示当加减号按钮被点击时,slider随之加1或减1,这种写法其实并不陌生,只不过这次是在控件中使用罢了。

在这一切都做好之后,先别急着使用,要首先生成一下代码。

控件调用

接下来要做的,就是在主窗口中调用我们自定义的控件,其xaml代码为

<local:AdvanceSlider Title="测试" Max="100" Min="0" Value="50"/>

非常简洁地就实现了下面的效果

在这里插入图片描述

自定义事件

有了这个基本控件的雏形还不够,这个控件需要可以注册事件,从而在数值发生变化的时候,可以让音量和语速发生变化。

自定义事件方法如下

public static readonly RoutedEvent ValueChangedEvent =
    EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, 
        typeof(RoutedEventHandler), typeof(AdvanceSlider));

public event RoutedEventHandler ValueChanged
{
    add { AddHandler(ValueChangedEvent, value); }
    remove { RemoveHandler(ValueChangedEvent, value); }
}

private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    RoutedEventArgs arg = new RoutedEventArgs();
    arg.RoutedEvent = ValueChangedEvent;
    RaiseEvent(arg);
}

首先,通过EventManager注册一个以ValueChanged为标志的事件ValueChangedEvent,然后设置ValueChanged,其原理与set,get如出一辙。接下来将这个新事件与现有的Slider事件联系起来,从而当Slider的值发生变化时,就可以触发这个新控件的ValueChanged事件。

更改音量和语速

有了这个AndvanceSlider,就可以非常便捷地创建音量语速更改控件了,其xaml代码为

<local:AdvanceSlider x:Name="sSoundVolume"
    Title="音量" Max="100" Min="0" Value="25" ValueChanged="sSoundVolume_ValueChanged"/>

<local:AdvanceSlider x:Name="sSpeechRate"
    Title="语速" Max="10" Min="-10" Value="0" ValueChanged="sSpeechRate_ValueChanged"/>

然后修改主窗口以及MySpeech类的代码

private void sSoundVolume_ValueChanged(object sender, RoutedEventArgs e)
{
    speech.setProp(volume: (int)sSoundVolume.Value);
    txt.Focus();
}

private void sSpeechRate_ValueChanged(object sender, RoutedEventArgs e)
{
    speech.setProp(rate : (int)sSpeechRate.Value);
    txt.Focus();
}

下面是MySpeech中创建的setProp函数,之所以设计得这么复杂,是因为我们使用的Speak相当于新开了一个线程,当其运行之后,任何设置都不会生效,所以在设置之前,要将其取消,并重新开启一段线程,这与快进快退的逻辑是相同的。

public void setProp(string voice = null, int rate=-100, int volume = -100)
{
    if(voice!=null)
        this.voice = voice;
    if (rate != -100)
        this.rate = rate;
    if (volume != -100)
        this.volume = volume;

    bool speaking = speech.State.ToString() == "Speaking";
    if (speaking)
    {
        st += charPosition;
        speech.SpeakAsyncCancelAll();
    }            
    setSpeech(this.voice, this.rate, this.volume);
    if(speaking)
        Speak();
}

最终其效果为,可以明显感受到语速的变化

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/655507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Java】Java核心要点总结 65:TreeSet 两种排序

文章目录 1. Comparable 和 Comparator区别比较2. TreeSet有两种实现指定排序规则的方式&#xff1a; 1. Comparable 和 Comparator区别比较 Comparable 是排序接口&#xff0c;若一个类实现了Comparable接口&#xff0c;就意味着“该类支持排序”。Comparator 是比较器&#x…

使用post请求建立长连接实现sse,接收后端主动发来的消息,实现chat-gpt的弹字效果,EventSource的应用

每日鸡汤&#xff1a;每个你想要学习的瞬间都是未来的你向自己求救 最近在做一个chat相关的功能&#xff0c;然后由于接口返回特别特别慢&#xff0c;所以需要搞一个慢慢等待的效果&#xff0c;就是接口一个单词一个单词的返回&#xff0c;然后前端收到一个展示一个&#xff0c…

Nucleo-F411RE (STM32F411)LL库体验 6 - EXTI外部中断的使用

Nucleo-F411RE &#xff08;STM32F411&#xff09;LL库体验 6 - EXTI外部中断的使用 1、简述 开发板蓝色按键连接PC13管脚&#xff0c;且断开时为高电平&#xff0c;闭合时低电平。我们将pc13设置为中断模式&#xff0c;低电平触发&#xff0c;当按键按下时&#xff0c;触发中…

Hadoop完全分布式运行环境的搭建

Hadoop完全分布式运行环境的搭建 文章目录 Hadoop完全分布式运行环境的搭建0. 写在前面1. 模板虚拟机环境准备安装模板虚拟机hadoop01虚拟机配置要求如下关闭防火墙&#xff0c;关闭防火墙开机自启创建普通用户配置新用户权限修改所属主和所属组卸载虚拟机自带的JDK重启虚拟机 …

【备战秋招】每日一题:4月23日美团春招第四题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检&#xff0c;为了更好的阅读体检&#xff0c;&#xff0c;可以查看我的算法学习博客第四题-01串的代价 在线评测链接:P1248 题目内容 塔子哥是一个喜欢研究密码的人&#xff0c;他经常在网上寻找各种有趣的密码挑战。他最近发现了一个神秘的网站&#xff…

指定字符串数组中每个元素sn的长度L如果sn长度比L短,则补充空格,且sn居中如果sn长度比L长,则保留sn左侧L个字符

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 指定字符串数组中每个元素sn的长度L 如果sn长度比L短&#xff0c;则补充空格,且sn居中 如果sn长度比L长&#xff0c;则保留sn左侧L个字符 [太阳]选择题 下列代码最后输出的结果是&#xff1f…

基于Java在线购物系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

MindFusion.Java Swing Pack 2023.R1 Crack

MindFusion.Java Swing Pack 2023.R1 改进了图表、电子表格和虚拟键盘。 6月 15&#xff0c; 2023 - 16&#xff1a;06 新版本 特征 MindFusion.Diagramming 的新功能 空间索引 - 创建项目位置索引&#xff0c;以便更快地进行命中测试和视口裁剪查询。这极大地提高了包含数…

ch8_1_CPU的结构和功能

1. cpu的结构 1.1CPU 的功能 控制器的功能 控制器的功能具体作用取指令指令控制分析指令操作控制执行指令&#xff0c; 发出各种操作命令控制程序输入与结果的输出时间控制总线管理处理中断处理异常情况和特殊请求数据加工 运算器的功能 实现算术运算 和 逻辑运算&#x…

基于Java多角色学生管理系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

基于Java网上服装销售系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

【大数据】可视化仪表板 - Superset的安装和使用

写在前面&#xff1a;博主是一只经过实战开发历练后投身培训事业的“小山猪”&#xff0c;昵称取自动画片《狮子王》中的“彭彭”&#xff0c;总是以乐观、积极的心态对待周边的事物。本人的技术路线从Java全栈工程师一路奔向大数据开发、数据挖掘领域&#xff0c;如今终有小成…

11-高性能JSON库——fastjson2

目录 1.具体使用 1.1.添加fastjson2依赖 1.2.常用类和方法 1.3.将JSON字符串转换成对象 1.3.1.JSON字符串转换成对象 1.3.2.JSON字符串转换成数组 1.4.将对象转换成JSON字符串 1.4.1.将对象转换成JSON字符串 1.4.2.将数组转换成 JSON 字符串 2.性能测试报告 3.总结 …

浪潮发布G2平台

2017年2月28日下午&#xff0c;浪潮在北京粤财JW万豪酒店以“智变”为主题&#xff0c;发布新一代智能存储平台G2&#xff0c;该平台基于统一架构和In系列智能软件设计&#xff0c;在保障”三高”特性满足企业级关键数据存储、处理需求的同时&#xff0c;更强调数据生命周期的智…

第六章 部署WSUS及RDS服务

❄️作者介绍&#xff1a;奇妙的大歪❄️ &#x1f380;个人名言&#xff1a;但行前路&#xff0c;不负韶华&#xff01;&#x1f380; &#x1f43d;个人简介&#xff1a;云计算网络运维专业人员&#x1f43d; 前言 适用范围&#xff1a;Windows Server 2022、Windows Server…

揭密ChatGPT背后团队鲜为人知的小秘密

ChatGPT引领的人工智能技术浪潮还在持续火爆&#xff0c;可是做出这款产品的OpenAI公司&#xff0c;熬得住多年的冷板凳&#xff0c;最终一飞冲天&#xff0c;他们是怎么做到的呢&#xff1f; 因此&#xff0c;我对这家企业的组织建设产生了浓厚的兴趣。我找啊找&#xff0c;最…

游戏开发日志13(利用PlayerPrefs来存储数据)

为游戏设置一个音量键&#xff0c;可以自由选择背景音乐是否开启&#xff0c;并且保存这个设置。 设计了UI如下&#xff1a; 其中BGM为Toggle&#xff0c;其余四个为Button 在canvas&#xff08;set&#xff09;上添加两个脚本&#xff1a;GameMnue&#xff0c;GameManage p…

【备战秋招】每日一题:4月15日美团春招第三题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检&#xff0c;为了更好的阅读体检&#xff0c;&#xff0c;可以查看我的算法学习博客第三题-交通规划 在线评测链接:P1237 题目内容 塔子哥所在的国家有 n 个城市&#xff0c;这 n 个城市排成一列&#xff0c;按顺序编号为 1,2,3,...,n。然而&#xff0c;由…

【备战秋招】每日一题:4月8日美团春招第五题:题面+题目思路 + C++/python/js/Go/java带注释

为了更好的阅读体检&#xff0c;为了更好的阅读体检&#xff0c;&#xff0c;可以查看我的算法学习博客第五题-RGP种树 在线评测链接:P1170 题目描述&#xff1a; 塔子哥是一位著名的冒险家&#xff0c;他经常在各种森林里探险。今天&#xff0c;他来到了道成林&#xff0c;…

【Django 网页Web开发】24. 实战项目:moudleForm的文件上传应用到城市管理(17)(保姆级图文)

目录 用户上传文件存放media如何启用1. 在urls.py中进行配置&#xff1a;2. 在settings.py中进行配置&#xff1a;3. 能够通过media的url访问文件 moudleForm上传文件实现城市管理1. moudle.py2. url.py3. city.py4. city.html5. 文件上传小结6. 城市管理效果总结 欢迎关注 『D…