终于解决了TTS的speak朗读完成问题

speak完成如何判断?如何使用SpVoice.SpeakCompleteEvent,这个问题困扰了我两天,最后看到msdn上的例子才知道要使用WaitForSingleObject函数处理它返回的时间句柄,之前的想speak或者偏移量的是多么荒谬啊。

peech API 5.3

Object: SpVoice
Type: Hidden

SpeakCompleteEvent Method

The SpeakCompleteEvent method gets an event handle from the voice that will be signaled when the voice finishes speaking.

The SpeakCompleteEvent method is similar to the WaitUntilDone method, but supports more sophisticated ways of waiting for the voice to finish speaking.

The WaitUntilDone method explicitly blocks program execution until the voice finishes. The SpeakCompleteEvent method does not block execution, but returns an event handle that can be used with API wait functions such as WaitForSingleObject.

Because these functions can wait for short periods of time, applications may be able to perform useful tasks while polling the event handle.

    
      SpVoice.SpeakCompleteEvent() As Long

  
Parameters
Return Value

A Long variable containing the event handle.

Example

The following code snippet demonstrates the use of the SpeakCompleteEvent method. The asynchronous Speak call returns immediately, and causes the voice to begin speaking as a background process. The SpeakCompleteEvent method returns the event handle of the speaking process. This handle is passed to WaitForSingleObject, which waits for a completion signal from the process. When the background speaking process signals its completion, the call to WaitForSingleObject returns, and the program continues.

    Dim objVoice As SpeechLib.SpVoice
Dim lngHandle As Long
Dim lngRtn As Long
Const INFINITE = -1&

Set objVoice = New SpVoice
objVoice.Speak "please wait until this text has been spoken", SVSFlagsAsync

lngHandle = objVoice.SpeakCompleteEvent             'Get a handle on this stream
lngRtn = WaitForSingleObject(lngHandle, INFINITE)   'Wait for completion
 一开始用 if WaitForSingleObject(SpVoice.SpeakCompleteEvent, INIFINTE) = WAIT_OBJECT_0 then判断发现当朗读时它会一直读下去,界面上按钮都不能点,
就改成WaitForSingleObject(SpVoice.SpeakCompleteEvent, 200)就好了,其中也参考了下面百度文库中的文章

一下子跳到等待函数 WaitForSingleObject, 是因为下面的 Mutex、Semaphore、Event、WaitableTimer 等同步手段都要使用这个函数; 不过等待函数可不止 WaitForSingleObject 它一个, 但它最简单.

function WaitForSingleObject(

hHandle: THandle; {要等待的对象句柄}

dwMilliseconds: DWORD {等待的时间, 单位是毫秒}

): DWORD; stdcall; {返回值如下:}

WAIT_OBJECT_0 {等着了, 本例中是: 等的那个进程终于结束了}

WAIT_TIMEOUT {等过了点(你指定的时间), 也没等着}

WAIT_ABANDONED {好不容易等着了, 但人家还是不让咱执行; 这一般是互斥对象}

//WaitForSingleObject 的第二个参数一般给常数值 INFINITE, 表示一直等下去, 死等.


WaitForSingleObject 等待什么? 在多线程里就是等待另一个线程的结束, 快来执行自己的代码; 不过它可以等待的对象可不止线程; 这里先来一个等待另一个进程结束的例子, 运行效果图:
clip_image001


代码文件:


unit Unit1;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject);

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

var

hProcess: THandle; {进程句柄}

{等待一个指定句柄的进程什么时候结束}

function MyThreadFun(p: Pointer): DWORD; stdcall;

begin

if WaitForSingleObject(hProcess, INFINITE) = WAIT_OBJECT_0 then

Form1.Text := Format('进程 %d 已关闭', [hProcess]);

Result := 0;

end;

{启动一个进程, 并建立新线程等待它的结束}

procedure TForm1.Button1Click(Sender: TObject);

var

pInfo: TProcessInformation;

sInfo: TStartupInfo;

Path: array[0..MAX_PATH-1] of Char;

ThreadID: DWORD;

begin

{先获取记事本的路径}

GetSystemDirectory(Path, MAX_PATH);

StrCat(Path, '/notepad.exe');

{用 CreateProcess 打开记事本并获取其进程句柄, 然后建立线程监视}

FillChar(sInfo, SizeOf(sInfo), 0);

if CreateProcess(Path, nil, nil, nil, False, 0, nil, nil, sInfo, pInfo) then

begin

hProcess := pInfo.hProcess; {获取进程句柄}

Text := Format('进程 %d 已启动', [hProcess]);

CreateThread(nil, 0, @MyThreadFun, nil, 0, ThreadID); {建立线程监视}

end;

end;

end.

  • 3
    点赞
  • 3
    评论
  • 1
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页

打赏作者

yingsuixindong

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值