5

だから私はイベントの例でMSAPI 5.4 TTSを試しました。SetNotifyCallbackFunction を利用する cmd プロンプト アプリを作成しましたが、渡した関数が呼び出されていません。私は C++ の専門家ではないので、これを解決するのに苦労しています。誰かが私を正しい方向に向けるか、少なくとも SetNotifyCallbackFunction の良い例を教えてください。

これが私のコードの簡略版です:

typedef void __stdcall SPNOTIFYCALLBACK(WPARAM wParam, LPARAM lParam);

void __stdcall outsideeventFunction(WPARAM, LPARAM);

void __stdcall outsideeventFunction(WPARAM wParam, LPARAM lParam){
    std::cout << "Event called::wParam: " << wParam << " lParam: " << lParam << std::endl;
    SPEVENT eventItem;
    memset(&eventItem, 0, sizeof(SPEVENT));
    while (SUCCEEDED(pV->GetEvents(1, &eventItem, NULL)))
    {
        bool exitNa = false;
        switch (eventItem.eEventId)
        {
        case SPEI_WORD_BOUNDARY:
            SPVOICESTATUS eventStatus;
            pV->GetStatus(&eventStatus, NULL);
            ULONG start, end;
            start = eventStatus.ulInputWordPos;
            end = eventStatus.ulInputWordLen;
            std::cout << "From event Test: " << start << ", " << end << std::endl;
            std::cout << "From event Length: " << theString.length() - 1 << ", " << start + end << std::endl;
            if (theString.length() - 1 <= start + end){
                std::cout << "From event Exit!" << std::endl;
                exitNa = true;
            }
            break;
        }

        SpClearEvent(&eventItem);
        if (exitNa){
            break;
        }
    }
    return;
}

int _tmain(int argc, TCHAR* argv [], TCHAR* envp [])
{
    pV = NULL;
    std::string nativeString("Hello world, this is a test! For the purpose of a longer message, I'll add another sentence. And here comes the new sentence.");
    SPNOTIFYCALLBACK *cb = &outsideeventFunction;
    if (FAILED(::CoInitialize(NULL)))
        return FALSE;

    HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **) &pV);
    if (SUCCEEDED(hr))
    {
        if (SUCCEEDED(pV->SetNotifyCallbackFunction(cb, 0, 0))){
            std::cout << "Success adding callback" << std::endl;
        }

        ULONGLONG ullMyEvents = SPFEI(SPEI_WORD_BOUNDARY);
        pV->SetInterest(ullMyEvents, ullMyEvents);
    }

    theString = std::wstring(nativeString.begin(), nativeString.end());

    printf("Speak: %s\n", nativeString.c_str());
    hr = pV->Speak(theString.c_str(), SPF_ASYNC, NULL);
    pV->WaitUntilDone(INFINITE);

    std::system("pause");
    pV->Release();
    pV = NULL;
    ::CoUninitialize();
    return TRUE;
}

このアプリの結果、単語の合成はスムーズに行われますが、outsideeventFunction が呼び出されることはありません。ご覧のとおり、SetInterest は適切に設定されています。どうすればこれを修正できますか?

4

1 に答える 1

6

2 つの問題:

1) SAPI ではイベント ターゲットを再割り当てできないため、次の行

pV->SetNotifyWin32Event();

常に失敗します。

2) イベントを配信するには、メッセージをポンピングする必要があります。だから電話する代わりに

pV->WaitUntilDone(INFINITE);

イベントが設定されるまで、ハンドルとポンプ メッセージを取得する必要があります。

HANDLE hWait = pV->SpeakCompleteEvent();
WaitAndPumpMessagesWithTimeout(hWait, INFINITE);

HRESULT WaitAndPumpMessagesWithTimeout(HANDLE hWaitHandle, DWORD dwMilliseconds)
{
    HRESULT hr = S_OK;
    BOOL fContinue = TRUE;

    while (fContinue)
    {
        DWORD dwWaitId = ::MsgWaitForMultipleObjectsEx(1, &hWaitHandle, dwMilliseconds, QS_ALLINPUT, MWMO_INPUTAVAILABLE);
        switch (dwWaitId)
        {
        case WAIT_OBJECT_0:
            {
                fContinue = FALSE;
            }
            break;

        case WAIT_OBJECT_0 + 1:
            {
                MSG Msg;
                while (::PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
                {
                    ::TranslateMessage(&Msg);
                    ::DispatchMessage(&Msg);
                }
            }
            break;

        case WAIT_TIMEOUT:
            {
                hr = S_FALSE;
                fContinue = FALSE;
            }
            break;

        default:// Unexpected error
            {
                fContinue = FALSE;
                hr = E_FAIL;
            }
            break;
        }
    }
    return hr;
}
于 2013-08-02T15:49:42.347 に答える