这几天在搞TTS发音,发现网上有关这方面的资料不多,特别是MFC使用TTS发音,后来在VC知识库发现一篇不错的文章,大家可以上去看一下(http://www.vckbase.com/document/viewdoc/?id=1051)但是文章写得太简单,而且他实现的方法一定要在创建MFC项目的时候在选上Automation,而我现在讲一下在我们以有的项目上添加TTS发音功能(创建项目的时候没有选上Automation)。
下面我把实现步骤写下来:
1、
下载
Microsoft Speech SDK, version 5.1
,要实现中文发音的话要再下载个
SimpChinese Speech Package
。
2、
安装了
Microsoft Speech SDK, version 5.1
后在
C:/Program Files/Common Files/Microsoft Shared/Speech
目录下找到
sapi.dll
。
3、
将
sapi.dll
复制到你的项目文件下。
4、
打开
MFC ClassWizard
,选择
Automation
页,单击按钮
"Add Class…"
,选择
"From a type library…",
选中
"sapi.dll"
文件,这时系统会出现
confirm Classes
对话框,询问将要导入的类(有
20
多个类)。如果只要实现发音功能,只要导入
IspeechObjectToken
,
IspeechObjectTokens
,
IspeechVoice
这
3
个,其它类的功能我还在研究中。(如果在建项目的时候勾选了
Automation
,系统会自动帮你生成
3
个文件,分别是
DlgProxy.cpp
,
DlgProxy.h
还有一个根据你项目名
.odl
文件,如果没有勾选上
Automation
就不会创建这三个文件,所以我们要实现发音功能,就要自己添加修改这三个文件)
5、
没有自动生成的文件怎么办呢?最好的办法就是新建一个项目,它的名称和你现有的项目名称一样,然后在创建
MFC Dialog Based
项目的时候,选上
Automation
,然后做步骤
4
,将它生成的
3
个文件复制并加入到你现有项目中。
6、
复制好后,就要在一些文件上添加修改代码了。下面我以一个名为
test
的工程为例子首先在
test.cpp
文件添加这些代码(红色):
BOOL CTestApp::InitInstance()
{
if (!AfxOleInit())
{
AfxMessageBox("OLE 程序初始化失败。请确认 OLE 库程序是正确的版本");
return FALSE;
}
AfxEnableControlContainer();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need.
#ifdef _AFXDLL
Enable3dControls(); // Call this when using MFC in a shared DLL
#else
Enable3dControlsStatic(); // Call this when linking to MFC statically
#endif
if (RunEmbedded() || RunAutomated())
{
// Register all OLE server (factories) as running. This enables the
// OLE libraries to create objects from other applications.
COleTemplateServer::RegisterAll();
}
else
{
// When a server application is launched stand-alone, it is a good idea
// to update the system registry in case it has been damaged.
COleObjectFactory::UpdateRegistryAll();
}
CTestDlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
7、
接着在
testDlg.h
文件添加以下代码:
#include "sapi.h"
class CtestDlgAutoProxy;
/
// CTestDlg dialog
class CTestDlg : public CDialog
{
DECLARE_DYNAMIC(CTestDlg);
friend class CtestDlgAutoProxy;
// Construction
public:
virtual ~CTestDlg();
CTestDlg(CWnd* pParent = NULL); // standard constructor
ISpeechObjectToken recoObject;
LPDISPATCH pDisp;
CLSID CLSID_SpVoice;
ISpeechVoice voice;
ISpeechObjectTokens voiceList;
// Dialog Data
//{{AFX_DATA(CTestDlg)
enum { IDD = IDD_TEST_DIALOG };
CComboBox m_voice; //
拖控件并添加control类型数据成员
long m_Rate;
long m_Vol;
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CTestDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
HICON m_hIcon;
CtestDlgAutoProxy* m_pAutoProxy;
// Generated message map functions
//{{AFX_MSG(CTestDlg)
8、
接着在
testDlg.cpp
添加下面代码:
#include "DlgProxy.h"
IMPLEMENT_DYNAMIC(CTestDlg, CDialog);
CTestDlg::CTestDlg(CWnd* pParent /*=NULL*/)
: CDialog(CTestDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CTestDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pAutoProxy = NULL;
}
CTestDlg::~CTestDlg()
{
if (m_pAutoProxy != NULL)
m_pAutoProxy->m_pDialog = NULL;
}
//
BOOL CTestDlg::OnInitDialog()
{
。。。。。。。。。。。。。
// TODO: Add extra initialization here
CLSIDFromProgID(L"SAPI.SpVoice", &CLSID_SpVoice);
voice.CreateDispatch(CLSID_SpVoice);
pDisp = voice.m_lpDispatch;
HRESULT hr = pDisp->QueryInterface(CLSID_SpVoice, (void**)&voice.m_lpDispatch);
if (hr == S_OK) {
pDisp->Release();
}
else {
voice.AttachDispatch(pDisp, TRUE);
}
m_Rate=0;//语速
voice.SetRate(m_Rate);
m_Vol=100; //音量
voice.SetVolume(m_Vol);
//用来获取支持多少种声音
voiceList=voice.GetVoices(NULL,NULL);
m_voice.SetCurSel(0);
voice.SetRefVoice(voiceList.Item(0)); //item(0)是英文发音,如果装了中文包可设item(3)
//为中文发音
return TRUE; // return TRUE unless you set the focus to a control
}
9、
添加个
button
void CTestDlg::OnButton1()
{
voice.Speak("you", 1);//
发音
}
10、
在
DlgProxy.cpp
找到下面一句代码:
IMPLEMENT_OLECREATE2(CtestDlgAutoProxy, "test.Application", 0xc1b93196, 0x3df8, 0x4a61, 0xb1, 0x22, 0xa4, 0xc2, 0x8e, 0xe2, 0x75, 0xdb)
并将它注释掉。(我不知道原因,但不注释的话运行会出错,如果有朋友知道原因的话请告诉我)
经过上面的步骤后,就可以实现到发音了,可以用
IspeechVoice
类的函数调发音的速度和音量等。我试过了,在默认情况下发音和金山词霸差不多。