我在C++ Builder中使用以下代碼來處理盲人的文本到語音應用程序控制(很可能類似的示例可以在Delphi中使用)。主窗體已檢查KeyPreview
屬性以啓用鍵F11預覽以開始說話活動(聚焦)控件。代碼是可行的,但有一些問題。這個例子在C++ Builder代碼中,但是從我發現的,Delphi遇到了同樣的問題,我發現的解決方案是一樣的。如果你有德爾福解決方案,隨時發佈,它是相似的無論如何。語音API(SAPI)在Windows 7上使用C++ Builder進行零點浮點除法
#include <sapi.h>
#include <WTypes.h>
//---------------------------------------------------------------------------
// Speak text string (synchronous function)
//---------------------------------------------------------------------------
bool SpeakText(UnicodeString Text)
{
ISpVoice* pVoice = NULL;
if (FAILED(::CoInitialize(NULL))) return false;
Word Saved8087CW = Default8087CW; // Disable floating point division by zero exception caused by Speak
Set8087CW(0x133f);
HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
if (SUCCEEDED(hr))
{
//pVoice->SpeakCompleteEvent()
//pVoice->SetSyncSpeakTimeout(1000);
hr = pVoice->Speak(WideString(Text).c_bstr(), SPF_DEFAULT, NULL);
pVoice->Release();
pVoice = NULL;
}
Set8087CW(Saved8087CW);
::CoUninitialize();
return true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key, TShiftState Shift)
{
UnicodeString Speaker;
if (Key == VK_F11)
{
if (Screen->ActiveControl->InheritsFrom(__classid(TButton))) { Speaker += "Button, " + static_cast<TButton*>(Screen->ActiveControl)->Caption + "."; }
else if (Screen->ActiveControl->InheritsFrom(__classid(TEdit))) { Speaker += "Edit box, " + static_cast<TEdit*>(Screen->ActiveControl)->Text + "."; }
}
if (Speaker != "") SpeakText(Speaker);
}
//---------------------------------------------------------------------------
問題:
pVoice->在線原因零浮點除法,如果我不使用
Set8087CW
功能覆蓋例外。這種情況只發生在Windows 7(可能是Vista和Windows 8)上,而不是Windows XP中的同一個程序中(編譯後的exe)。有沒有不使用Set8087CW
的解決方案?刪除這些行會導致問題和異常。我有BCB2010。功能是同步的,在程序結束讀取文本之前不會關閉或返回控制權。這是較長文本的問題。它也阻止程序事件。有沒有辦法讓它異步或引入一個事件來定期檢查F11鍵狀態,如果F11再次按下,它會停止讀取和取消初始化對象?例如輪詢每300毫秒(或每個單詞等後)按鍵F11,如果按下,停止說話?或者運行它線程?
SAPI是否有內存泄漏,因爲有些在各種網站上寫入?
以上代碼可以使用
OleCheck
而不是CoCreateInstance
和CoUninitialize
?
UPDATE爲那些尋找溶液通過雷米勒博的建議:
SavedCW = Get8087CW();
Set8087CW(SavedCW | 0x4);
hr = pVoice->Speak(WideString(Text).c_bstr(), SPF_DEFAULT | SPF_ASYNC, NULL);
pVoice->WaitUntilDone(-1); // Waits until text is done... if F11 is pressed simply go out of scope and speech will stop
Set8087CW(SavedCW);
還找到詳細的例子在CodeRage 4會話:http://cc.embarcadero.com/item/27264
我嘗試了上面的代碼,但沒有講話聲。我將hr的值設爲null。我已經打開了一個新的幫助線索:http://stackoverflow.com/questions/27820940/ms-sapi-5-1-issue-with-c你能幫我嗎? – programmer 2015-01-07 14:26:06
@programmer您的問題不適用於C++ Builder編譯器,上述解決方案適用於C++ Builder。 – Coder12345 2015-01-07 18:00:41
感謝您的評論。對於我發佈的問題,你有什麼建議嗎?我希望我能使它工作。 – programmer 2015-01-08 02:25:21