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類的函數調發音的速度和音量等。我試過了,在默認情況下發音和金山詞霸差不多。