tts语音朗读,终于解决了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 _disibledevent=> 一开始用 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终于解决了TTS的speak朗读完成问题tts语音朗读

代码文件:

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.
Tags:  tts朗读功能 tts听书朗读 tts文本朗读 tts朗读 tts语音朗读

延伸阅读

最新评论

发表评论