我们知道,win7系统自带有讲述人,即可以机器读出当前内容,具体可以将电脑锁定,然后点击左下角的按钮即可。之前在用Matlab写扫雷游戏的时候,也曾经调用过讲述人来进行游戏的语音提示。具体的Matlab脚本文件如下:

 sp=actxserver('SAPI.SpVoice');sp.Speak('你好,欢迎来到西安电子科技大学!Hello,Welcome to XD University!')
       Qt调用讲述人,需要使用专门的类,具体可以参考http://lynxline.com/qtspeech-say-hello-world  一文,文中大致介绍了该类的使用方法。下面我就通过使用该类来实现讲述人的调用。
    首先建立一个dialog类型的gui项目,将上面所说的类QtSpeech类的头文件speech.h和源文件speech.cpp添加到工程中,这样项目中就有5个文件:dialog.h、speech.h、main.cpp、dialog.cpp、speech.cpp。当然还有界面文件dialog.ui。在界面文件中添加QTextEdit控件用于输入你要读取的文字,然后在其槽函数中添加QtSpeech的发音功能,添加QPushButton控件来控制发音。具体的各个文件源代码如下:

1、dialog.h

#ifndef DIALOG_H
#define DIALOG_H
#include <QDialog>
#include"speech.h"
namespace Ui {
class Dialog;
}
class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = 0);
    ~Dialog();

private slots:
    void on_pushButton_clicked();
private:
    Ui::Dialog *ui;
};
#endif // DIALOG_H

2、speech.h

#ifndef SPEECH_H
#define SPEECH_H
#include <QObject>
class QtSpeech : public QObject {
    Q_OBJECT
public:
    // 处理异常情况
    struct Error { QString msg; Error(QString s):msg(s) {} };
    struct InitError : Error { InitError(QString s):Error(s) {} };
    struct LogicError : Error { LogicError(QString s):Error(s) {} };
    struct CloseError : Error { CloseError(QString s):Error(s) {} };
    //定义数据类型
    struct VoiceName { QString id; QString name; };
    typedef QList<VoiceName> VoiceNames;
    //定义构造函数
    QtSpeech(QObject * parent);
    QtSpeech(VoiceName n = VoiceName(), QObject * parent =0L);
    virtual ~QtSpeech();
    const VoiceName & name() const; //要读的内容
    static VoiceNames voices();     //要读的内容
    void say(QString) const;                                    //同步发音
    void tell(QString) const;                                   //异步发音
    void tell(QString, QObject * obj, const char * slot) const; //发音结束时,有停顿
    /*******************/
    void pause(void) const;//暂停
    void resume(void) const;//从暂停中恢复
    void stop(void) const;//停止发音
    /******************/
signals:
    void finished();
protected:
    virtual void timerEvent(QTimerEvent *);
private:
    class Private;
    Private * d;
};
//}
#endif // SPEECH_H

3、main.cpp

#include <QApplication>
#include"dialog.h"
int main(int argc, char *argv[]){
    QApplication app(argc, argv);
    Dialog dlg;
    dlg.show();
    return app.exec();
}

4、dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
}
Dialog::~Dialog()
{
    delete ui;
}
void Dialog::on_pushButton_clicked()
{
    QtSpeech *speaker = new QtSpeech(this);
    speaker->tell(ui->textEdit->toPlainText(),speaker,SLOT(onSpeechFinished()));
   // speaker.stop();
}

5、speech.cpp

#include "speech.h"
#include <QString>
#include <QPointer>
#include <QList>
#include <QTimerEvent>
#undef UNICODE
#include <sapi.h>
#include <sphelper.h>
#include <comdef.h>
#define UNICODE
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
// some defines for throwing exceptions
#define Where QString("%1:%2:").arg(__FILE__).arg(__LINE__)
#define SysCall(x,e) {\
    HRESULT hr = x;\
    if (FAILED(hr)) {\
        QString msg = #e;\
        msg += ":"+QString(__FILE__);\
        msg += ":"+QString::number(__LINE__)+":"+#x+":";\
        msg += _com_error(hr).ErrorMessage();\
        throw e(msg);\
    }\
}
// internal data
class QtSpeech::Private {
public:
    Private()
        :onFinishSlot(0L),waitingFinish(false) {}
    VoiceName name;
    static const QString VoiceId;
    typedef QPointer<QtSpeech> Ptr;
    static QList<Ptr> ptrs;
    CComPtr<ISpVoice> voice;
    const char * onFinishSlot;
    QPointer<QObject> onFinishObj;
    bool waitingFinish;
    class WCHAR_Holder {
    public:
        WCHAR * w;
        WCHAR_Holder(QString s)
            :w(0) {
            w = new WCHAR[s.length()+1];
            s.toWCharArray(w);
            w[s.length()] =0;
        }
        ~WCHAR_Holder() { delete[] w; }
    };
};
const QString QtSpeech::Private::VoiceId = QString("win:%1");
QList<QtSpeech::Private::Ptr> QtSpeech::Private::ptrs = QList<QtSpeech::Private::Ptr>();
//类的定义
QtSpeech::QtSpeech(QObject * parent)
    :QObject(parent), d(new Private)
{
    CoInitialize(NULL);
    SysCall( d->voice.CoCreateInstance( CLSID_SpVoice ), InitError);
    VoiceName n;
    WCHAR * w_id = 0L;
    WCHAR * w_name = 0L;
    CComPtr<ISpObjectToken> voice;
    SysCall( d->voice->GetVoice(&voice), InitError);
    SysCall( SpGetDescription(voice, &w_name), InitError);
    SysCall( voice->GetId(&w_id), InitError);
    n.name = QString::fromWCharArray(w_name);
    n.id = QString::fromWCharArray(w_id);
    voice.Release();
    if (n.id.isEmpty())
        throw InitError(Where+"No default voice in system");
    d->name = n;
    d->ptrs << this;
}
QtSpeech::QtSpeech(VoiceName n, QObject * parent)
    :QObject(parent), d(new Private)
{
    ULONG count = 0;
    CComPtr<IEnumSpObjectTokens> voices;
    CoInitialize(NULL);
    SysCall( d->voice.CoCreateInstance( CLSID_SpVoice ), InitError);
    if (n.id.isEmpty()) {
        WCHAR * w_id = 0L;
        WCHAR * w_name = 0L;
        CComPtr<ISpObjectToken> voice;
        SysCall( d->voice->GetVoice(&voice), InitError);
        SysCall( SpGetDescription(voice, &w_name), InitError);
        SysCall( voice->GetId(&w_id), InitError);
        n.name = QString::fromWCharArray(w_name);
        n.id = QString::fromWCharArray(w_id);
        voice.Release();
    }
    else {
        SysCall( SpEnumTokens(SPCAT_VOICES, NULL, NULL, &voices), InitError);
        SysCall( voices->GetCount(&count), InitError);
        for (int i =0; i< count; ++i) {
            WCHAR * w_id = 0L;
            CComPtr<ISpObjectToken> voice;
            SysCall( voices->Next( 1, &voice, NULL ), InitError);
            SysCall( voice->GetId(&w_id), InitError);
            QString id = QString::fromWCharArray(w_id);
            if (id == n.id) d->voice->SetVoice(voice);
            voice.Release();
        }
    }
    if (n.id.isEmpty())
        throw InitError(Where+"No default voice in system");
    d->name = n;
    d->ptrs << this;
}
QtSpeech::~QtSpeech()
{
    d->ptrs.removeAll(this);
    delete d;
}
const QtSpeech::VoiceName & QtSpeech::name() const {
    return d->name;
}
QtSpeech::VoiceNames QtSpeech::voices()
{
    VoiceNames vs;
    ULONG count = 0;
    CComPtr<IEnumSpObjectTokens> voices;
    CoInitialize(NULL);
    SysCall( SpEnumTokens(SPCAT_VOICES, NULL, NULL, &voices), LogicError);
    SysCall( voices->GetCount(&count), LogicError);
    for(int i=0; i< count; ++i) {
        WCHAR * w_id = 0L;
        WCHAR * w_name = 0L;
        CComPtr<ISpObjectToken> voice;
        SysCall( voices->Next( 1, &voice, NULL ), LogicError);
        SysCall( SpGetDescription(voice, &w_name), LogicError);
        SysCall( voice->GetId(&w_id), LogicError);
        QString id = QString::fromWCharArray(w_id);
        QString name = QString::fromWCharArray(w_name);
        VoiceName n = { id, name };
        vs << n;
        voice.Release();
    }
    return vs;
}
void QtSpeech::tell(QString text) const {
    tell(text, 0L,0L);
}
void QtSpeech::tell(QString text, QObject * obj, const char * slot) const
{
    if (d->waitingFinish)
        throw LogicError(Where+"Already waiting to finish speech");
    d->onFinishObj = obj;
    d->onFinishSlot = slot;
    if (obj && slot)
        connect(const_cast<QtSpeech *>(this), SIGNAL(finished()), obj, slot);
    d->waitingFinish = true;
    const_cast<QtSpeech *>(this)->startTimer(100);
    Private::WCHAR_Holder w_text(text);
    SysCall( d->voice->Speak( w_text.w, SPF_ASYNC | SPF_IS_NOT_XML, 0), LogicError);
}
void QtSpeech::say(QString text) const
{
    Private::WCHAR_Holder w_text(text);
    SysCall( d->voice->Speak( w_text.w, SPF_IS_NOT_XML, 0), LogicError);
}
void QtSpeech::timerEvent(QTimerEvent * te)
{
    QObject::timerEvent(te);
    if (d->waitingFinish) {
        SPVOICESTATUS es;
        d->voice->GetStatus( &es, NULL );
        if (es.dwRunningState == SPRS_DONE) {
            d->waitingFinish = false;
            killTimer(te->timerId());
            finished();
        }
    }
}
/************************/
void QtSpeech::pause(void) const{//暂停
    SysCall( d->voice->Pause(), LogicError);
}
void QtSpeech::resume() const{//恢复
    SysCall(d->voice->Resume(), LogicError);
}
void QtSpeech::stop() const{//停止
    SysCall(d->voice->Speak(NULL, SPF_PURGEBEFORESPEAK, 0), LogicError)
}
/***************************/
//}
程序结果如下:

基于Qt的词典开发系列

  1. 词典框架设计及成品展示
  2. 本地词典的设计
  3. 开始菜单的设计
  4. 无边框窗口的缩放与拖动
  5. 无边框窗口的拖动
  6. 界面美化设计
  7. 调用网络API
  8. 用户登录及API调用的实现
  9. JSON数据解析
  10. 国际音标的显示
  11. 系统托盘的显示
  12. 调用讲述人
  13. 音频播放
  14. 自动补全功能
  15. HTML特殊字符及正则表达式
  16. 后序
作品下载地址(发布版):http://download.csdn.net/detail/tengweitw/8548767
作品下载地址(绿色版):http://download.csdn.net/detail/tengweitw/8830495
源码下载地址:http://download.csdn.net/detail/tengweitw/8830503

原文:http://blog.csdn.net/tengweitw/article/details/38306803

作者:nineheadedbird

【Qt编程】基于Qt的词典开发系列<十二>调用讲述人的更多相关文章

  1. 【Qt编程】基于Qt的词典开发系列<十>--国际音标的显示

    在年前的一篇文章中,我提到要学习Qt.于是在这学期看了一个月的qt.现在大致对qt有了一些了解.但是现在导师又把我调到了android应用开发平台,所以说qt的学习要搁置了.本打算这学期做一个单词查询 ...

  2. 【Qt编程】基于Qt的词典开发系列<十五>html特殊字符及正则表达式

    1.html特殊字符的显示 我们知道html语言和C语言一样也有一些特殊字符,它们是不能正常显示的,必须经过转义,在网上可以查到如何显示这些字符,如下图所示: 上图给了最常用的特殊字符的显示,下面我们 ...

  3. 【Qt编程】基于Qt的词典开发系列<十四>自动补全功能

    最近写了一个查单词的类似有道词典的软件,里面就有一个自动补全功能(即当你输入一个字母时,就会出现几个候选项).这个自动补全功能十分常见,百度搜索关键词时就会出现.不过它们这些补全功能都是与你输入的进行 ...

  4. BizTalk开发系列(十二) Schema设计之Group与Order

    开发BizTalk项目的时候会先约定各系统之间往来的消息格式. 由于BizTalk内部唯一使用XML文档.因此消息的格式为XML Schema(XML Schema 用于描述 XML 文档的结构).虽 ...

  5. UWP开发砸手机系列(二)—— “讲述人”识别自定义控件Command

    上一篇我们提到如何让“讲述人”读出自定义的CanReadGrid,但“讲述人”仍然无法识别CanReadGrid上绑定的Command.XAML代码如下: <StackPanel> < ...

  6. 【Qt编程】基于Qt的词典开发系列<二>--本地词典的设计

    我设计的词典不仅可以实现在线查单词,而且一个重大特色就是具有丰富的本地词典库:我默认加入了八个类型的词典,如下所示: 由于是本人是通信专业,因此加入了华为通信词典.电子工程词典,又由于我喜爱编程,也加 ...

  7. 【Qt编程】基于Qt的词典开发系列--后序

    从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点 ...

  8. 【Qt编程】基于Qt的词典开发系列<六>--界面美化设计

    本文讲一讲界面设计,作品要面向用户,界面设计的好坏直接影响到用户的体验.现在的窗口设计基本都是扁平化的,你可以从window XP与window 8的窗口可以明显感觉出来.当然除了窗口本身的效果,窗口 ...

  9. 【Qt编程】基于Qt的词典开发系列<三>--开始菜单的设计

    这篇文章讲讲如何实现开始菜单(或者称为主菜单)的设计.什么是开始菜单呢?我们拿常用的软件来用图例说明,大多数软件的开始菜单在左下角,如下图: 1.window 7的开始菜单 2.有道词典的主菜单 3. ...

随机推荐

  1. webstorm工具使用详解

    webstorm简单介绍 官网地址:http://www.jetbrains.com/webstorm/features/index.html 参考地址:http://www.html5jscss.c ...

  2. Spring的DataSource配置、将Hibernate配置全部写到Spring配置

    DataSource可以集中管理数据库连接,减少维护工作量,使部署更简单: Spring的DataSource配置:(Spring数据源配置)这里使用dbcp,还有很多其他的如c3p0,jdbc,jn ...

  3. SYBASE的select into与insert into使用和区别

    对于表的部分或全部字段的复制,Sybase数据库提供了两种方式:select into和insert into. select into: 语法:select  value1, value2, val ...

  4. 1.QT中的容器QVector,QList,QSet,QMap,QQueue,QStack,QMultiMap,QSingleList等

    1  新建一个项目 在pro文件中只需要加上CONFIG += C++11 main.cpp #include <QMap> int main() { QMap<int,QStrin ...

  5. 1Nginx+fastdfs分布式文件存储

     准备,将所需的软件传到服务器上,服务器的列表如下: fastdfs-nginx-module_v1.15.tar.gz FastDFS_v4.06.tar.gz libevent-2.0.21- ...

  6. Nginx模块之SessionSticky

    0 工作原理 Session Sticky 模块在upstream 返回响应后,向客户的浏览器写入 Cookie ,默认名为route ,保存的内容是一个 md5 码. 之后,模块接收到客户浏览器的请 ...

  7. ROS_Kinetic_16 ubuntu中安装使用Matlab和ROS

    ROS_Kinetic_16 ubuntu(16.04)中安装使用Matlab(2015b)和ROS(kinetic) 参考网址:http://cn.mathworks.com/hardware-su ...

  8. 最简单的基于FFmpeg的AVDevice例子(屏幕录制)

    =====================================================最简单的基于FFmpeg的AVDevice例子文章列表: 最简单的基于FFmpeg的AVDev ...

  9. Zookeeper运维

    一.运维配置         参考:http://zookeeper.apache.org/doc/r3.4.6/zookeeperAdmin.html#sc_configuration 基础配置   ...

  10. 序列化与反序列化中serialVersionUID的作用(通俗易懂)

    serialVersionUID:字面意思上是序列化的版本号,这个在刚刚接触java编程时,学序列化大家一般都不会注意到,在你一个类序列化后除非你强制去掉了myeclipse中warning的功能,在 ...