【Qt编程】调用讲述人

我们知道,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编程】调用讲述人,布布扣,bubuko.com

时间: 2024-10-19 21:17:49

【Qt编程】调用讲述人的相关文章

【Qt编程】基于Qt的词典开发系列&amp;lt;九&amp;gt;--JSON数据解析

在上一篇文章<用户登录及API调用的实现>中,我通过程序实现了用户登录及API调用的实现.从而能够实现网络查词.添词的操作.可是.从上文中能够看到.调用API后返回的是JSON格式的数据,例如以下图所看到的(在QtCreator中的显示): 为了更好的观察JSON格式.我整理后显演示样例如以下: 显然.为了显示查词的结果,我们必须在上图中提取实用的信息,并正确的显示出来. 上图中每一行内容的意思我已经在文章<调用网络API>中作了解释.我在词典中选择想要显示的内容有:单词本身.单词

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

从去年八月份到现在,总算完成了词典的编写以及相关技术文档的编辑工作.从整个过程来说,文档的编写比程序的实现耗费的时间更多.基于Qt的词典开发系列文章,大致包含了在编写词典软件过程中遇到的技术重点与难点.每篇文章都完成了一个小的功能,所给的代码都基本上是可以独立运行的.本系列文章对于想要自己动手完成词典软件的程序员来说具有很好的参考价值,对于想要编写其它软件的人来说也具有参考意义. 词典软件制作的初衷 在2013的年终总结中,我提过想要学习一门界面编程语言,后来就选中了Qt.于是在2014年上半年

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

上一篇我们提到如何让“讲述人”读出自定义的CanReadGrid,但“讲述人”仍然无法识别CanReadGrid上绑定的Command.XAML代码如下: <StackPanel> <TextBlock Text="{x:Bind Title,Mode=OneWay}" Foreground="White"></TextBlock> <local:CanReadGrid Background="Red"

Qt编程18:Qt调色板QPalette的使用

QPalette类有两个枚举类型, 枚举 1.ColorGroup CorGroup指的是3中不同的状态(什么时候设置颜色): 1>Active:获得焦点的状态. 2>Inactive:未获得焦点的状态. 3>Disable:不可用状态. 通常情况下,Active状态与Inactive状态下颜色显示是一致的,当然也可根据需要设置成不一样的颜色 2.ColorRole(设置什么颜色). ColorRole指的是颜色主题,即对窗体中不同部位颜色的分类,如QPalette::Window是指背

Matlab.NET混合编程调用Figure窗体

原文:[原创]Matlab.NET混合编程调用Figure窗体 1.前言 做Matlab.NET混合编程好几年了,虽然Matlab很多函数忘记得差不多了,但基本的东西还是能熟练使用.特别是在C#调用Matlab函数这方面,积累了比较多的经验,和使用经验密切相关.根据很多朋友经常遇到的WinForm窗体混编调用Matlab的Figure的问题,花了一些功夫,把这个封装为C#控件,使得大家可以很容易调用Matlab的Figure了. 2.Matlab.NET混合编程概述 这方面就不仔细阐述了,主要是

Qt编程的一些技巧

1.Qt程序在运行过程中,调用函数(如lcdNumber->display(num))显示数据到界面上时,并不会马上刷新屏幕显示,而是要等主程序运行到函数a.exec()时,才刷新屏幕,如下 因此想在循环中刷新界面显示数据,需要在显示函数之后加上函数 qApp->processEvents(); 就可以实现刷新屏幕. 2.Qt中隐藏鼠标指针和免去终端中运行程序时需要输参数-qws 在main函数中 QApplication a(argc, argv,QApplication::GuiServe

QT笔记(1)--QT编程环境搭建

一.QT简介 Qt  是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,易于扩展,允许组件编程.2008年,奇趣科技被诺基亚公司收购,QT也因此成为诺基亚旗下的编程语言工具.2012年,Qt被Digia收购.2014年4月,跨平台集成开发环境Qt Creator 3.1.

Qt中调用PolarSSL库(一)

最近一直在学习SSL相关的知识,也是先了解理论相关的知识,主要是SSL相关的基本概念和连接建立过程,主要是基于PolarSSL开源库进行学习.学习完了之后就希望能给有所运用,就想用Qt写一个简单的程序,增加对SSL相关概念的把握和对PolarSSL库的运用.当然,最终希望是可以使用Qt做一个比较完善的工具,帮助大家更好的理解和学习SSL相关知识.这都是后话,在第一篇里面,我们就简单用例子展示如何在Qt里面调用PolarSSL库. 这篇博客主要是讲解Qt里面调用PolarSSL库,至于SSL相关概

【Qt编程】音频播放

在上一篇文章中,我是在Qt4平台上调用本地发音的,后来由于用到JSON解析,就将平台转到了Qt5,因为Qt5自带解析JSON的类.然后发现上一篇文章的方法无法运行,当然网上可以找到解决方法,我在这里直接调用Qt自带的类进行网络音频播放和本地播放.比较适用于单词的网上发音和无网情况下的本地发音,而不用将音频文件下载下来,占用太多内存. 为了简便起见,工程里只有一个main.cpp文件,不要忘了在.pro文件中加入下面两行: QT += multimedia CONFIG += qaxcontain