zoukankan      html  css  js  c++  java
  • 【Qt程序】基于Qt词典开发系列<十二>呼叫讲述

           我们知道,win7系统自带有讲述人,即能够机器读出当前内容,详细能够将电脑锁定。然后点击左下角的button就可以。之前在用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加入到project中。这样项目中就有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



  • 相关阅读:
    恢复oracle中误删除drop掉的表
    mysql安装教程(小白入门)
    各版本mysql下载安装教程(超详细,超全)
    Jetbrains系列产品2019.3.3及以下版本最新激活方法
    老友记全季高清视频(中英字幕)及学习资料(剧本,音频,台词)等等!
    电脑桌面快捷方式小箭头的去与留!
    Sublime Text 3破解教程及应用技巧和诀窍(完美激活)
    7个堪称经典的电脑小技巧,让你办公事半功倍!
    怎么优化,美化电脑桌面(Fences v3.0.9 中文破解版)来这里教你。
    JAVA
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5050182.html
Copyright © 2011-2022 走看看