|
0 S9 [; k' i& l1 B: }0 z' l
华 中 师 范 大 学 卢 小 海(flier@126.com) , b! A: h ^: E; G+ j* T; j: f
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 ^- G {& D" }3 R
( ~) r# o6 v% N9 i9 q. D
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
1 n* G k( p9 b* V# Y9 v; P+ W) q----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
% g) x1 O* v; U----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 % T6 k0 R k7 [
----再 在Delphi 里 新 建 一 个Application。
& y8 R# y! F/ o----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
+ ?* Q# @3 ?( w) U. E6 L: P----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
, t; J! q$ v, {6 Y% \! f----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
% z/ u" z- p I w' V ...1 u( u) ]1 Y: w
procedure TfrmMain.FormCreate(Sender: TObject);) `) h. D4 _0 [# z$ G. y
begin
1 _5 I o' D; w& h FISpeech := CoVTxtAuto_.Create;
3 I' A3 ^/ R$ U" f( n" ] FISpeech.Register(‘Demo Site', ‘Demo App');1 Y0 N, f h: n3 e, {
end;6 V/ d7 P+ t0 M, L
... : @' q3 K7 k3 i9 P% I9 A
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
) L7 A7 C9 w7 ~----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 + E" M& W! }# J
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 7 g6 J: q6 ?1 f X7 v4 d
Form 定 义 如 下:
2 B" c5 w) R4 S3 c2 z( g6 A object frmMain: TfrmMain
( z6 I# N9 c- b8 n, I1 _" ~ Left = 2969 \4 N a; b' L
Top = 187
2 a6 @. e5 [% ], n/ m3 K2 w7 {4 w BorderStyle = bsDialog$ P* O* P/ z+ z" M
Caption = ‘ 英 文 全 文 朗 读 演 示'
) I: k/ U/ | E ClientHeight = 185# g: M0 q5 Y# Y+ V6 r2 Y+ c
ClientWidth = 456. s* H( L, R! w0 p# w, e/ t
Color = clBtnFace
4 I4 C( v0 \. z" d! _7 G; ~+ { Font.Charset = GB2312_CHARSET- t. J3 \5 I8 ], n* l$ g
Font.Color = clWindowText
/ o* j4 ]+ ]4 w$ f8 e/ ^% i Font.Height = -12
. I4 o$ y8 l7 {; I% c: _% m Font.Name = ‘ 宋 体'
9 I% [: V2 g! H: y) H& v; S6 F l+ T Font.Style = []" S8 y9 B- }# a+ h) |2 ?6 b! [5 B
OldCreateOrder = False" m# R+ ~7 Z. f* C. ^
Position = poDesktopCenter
- R/ R2 s* z, ~9 }* I5 l( ? OnCreate = FormCreate
- X0 R) A+ l& m" A+ j3 _ PixelsPerInch = 96
+ v3 P8 S/ E. ^2 @4 S& u TextHeight = 12
1 u7 O8 @& V) o: z1 ^5 q object memText: TMemo
6 f6 \% A# K+ ]6 n7 @ Left = 8# e+ k% G( ]8 Q+ x1 V3 z. L6 j
Top = 8) o/ T8 ?0 y6 z. v* z6 _- Q
Width = 361
! u9 `! E- r" N" Q( T Height = 169
( v& r& r0 L7 J% S* a( A ScrollBars = ssVertical
% e) G! n6 X6 V- D7 m TabOrder = 0
3 O: ~6 ?, @4 ]! ~5 a6 i end2 I; c+ h4 w+ m; C% x
object btnRead: TButton
5 y" Q: ]+ E% T( \ Left = 376! s1 l$ ~: v3 F3 @
Top = 8
/ G; A9 S2 @5 A Width = 75. K8 R" d- B: y0 U
Height = 25
4 U& V/ U* R6 f6 y& } Caption = ‘ 朗 读( &R)'3 X: a+ u9 ?% p4 I5 ?: @
TabOrder = 1! Y$ g8 ?7 ~6 S. ~# R; f9 s; q! C8 m
OnClick = btnReadClick1 U: Z# E j- Z1 Y* u( ?* O
end. q" @/ s, F2 s m% r; k
object btnPause: TButton
2 R& d" K, k. y9 {" H/ S8 r3 T2 B Left = 376
6 N5 S' ]6 \9 F3 L8 s Top = 40
2 @: x# A: Z9 }9 Y" N( z Width = 75
( L# b0 m* a/ d: e3 K Height = 25
7 j( `7 H' E3 B5 j Caption = ‘ 暂 停( &P)'
8 ?5 v" y) V1 d4 F' t Enabled = False
2 n! l+ } {0 t TabOrder = 2
% }/ ]/ x# I1 s- B6 r. k: E OnClick = btnPauseClick
$ Q7 J* e f5 h, x! d# { end
, _. J( T& \0 N4 E' E3 X object btnStop: TButton$ ~6 Q4 x& X2 a- S9 O' y- \: G0 r
Left = 376
2 J3 \- x4 r6 [8 F Top = 72+ k5 o: Y0 W! e! \- r; e9 v
Width = 75/ m/ U4 K: D6 b u3 I! t" _
Height = 250 i- N# |. w. S. L5 ]" Z
Caption = ‘ 停 止( &S)'. {% R4 M) ^3 ]5 |2 Z4 F
Enabled = False$ t) Q$ }) G- V
TabOrder = 3
( q/ s1 X# \ G4 j& p- v6 Z6 e7 A OnClick = btnStopClick
: ]2 c4 [) b; z2 N! s end1 f2 _- u; \) ^. g, Y8 B
object btnForward: TButton
; b6 H# h5 k* u( h$ @3 Z2 \ Left = 376
0 D" x! [9 W7 q% f b! G7 p' S Top = 120( E8 a. S" Z2 H" a2 B% U4 C( F
Width = 75
7 q+ P; d5 n! \$ _, s, f Height = 25* N% A' w) C0 [) Z' I' h- V
Caption = ‘ 下 一 句( &N)', n: l+ h0 T% n" p o3 s+ H
Enabled = False: ]7 h1 T1 g3 ?: O. I; T% p2 d
TabOrder = 41 j9 {' u* G( C8 u' {0 ~8 W5 u
OnClick = btnForwardClick
& ?; S/ }7 e/ e, U end
6 E! }' J: D4 ~+ d& K. u9 [ object btnRewind: TButton" M+ D5 d9 u) ?
Left = 376
% I9 G/ a- B; l( Y! ^1 U7 D Top = 152
7 |' u S" Y! P2 C7 V Width = 75* b' ~" d* S: y& @/ u. q' v1 Q
Height = 25
: K* b$ d% \7 N2 d Caption = ‘ 上 一 句( &W)': [3 |: _. _- d/ W4 W8 A& t& h
Enabled = False
/ M& {7 |5 h' q# g5 v TabOrder = 5% a# n! k+ M6 W T
OnClick = btnRewindClick1 X2 T& |. r; b+ T* h* R
end
! g8 D3 S, i- p$ r# p5 v/ H end 1 d8 z! b4 ?5 u; G
----关 键 代 码 段 如 下: 6 |# S! G0 y: Y- s# X+ L) B/ _
---- 1. 朗 读 与 停 止 + g# y0 E5 Z/ C9 a; x* N) B7 B
...* t6 N' h3 s2 y. r) B) q
procedure TfrmMain.btnReadClick(Sender: TObject);# m4 h+ A4 m4 p P$ t- \8 \7 \
begin
2 m2 |% }, ?$ t. g! w FISpeech.Speak(memText.Lines.Text, vtxtst_
# t v* ^! F% O% m- E) jREADING);( e& `4 e M5 R6 g
btnPause.Enabled := True;
! E! B/ x1 y! ~: S btnStop.Enabled := True;9 j! i7 d9 ]6 Y. Z6 B3 ^
end;: u# g! Y: s6 p) q9 O; M1 B. ]. p
/ Q/ M' g- L, A
procedure TfrmMain.btnStopClick(Sender: TObject);
0 { f F* _7 n5 Z9 n7 g% } n begin
& K, r' W1 u. a8 u6 m$ [ FISpeech.StopSpeaking;
: v7 V6 w* @! a. X btnPause.Enabled := False;6 Q _8 o+ B9 _: _; [! I) L- I
btnStop.Enabled := False;) Z% @% c# F& @. `7 u5 s, Q
btnPause.Caption := ‘ 暂 停( &P)';' @- b: J- u( w3 ^- s
end;
% q" |9 m; [! @' O! }" m* g ... 4 \" o6 z8 I- g
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 8 N- T6 I# c: k" J
! \5 Y {3 v$ c. a: U9 M' n* R; X
---- 2. 暂 停 与 恢 复 % d( F5 R4 U& U( ^7 P
...
' v$ _9 e" z! }; T" o, Z# P- |procedure TfrmMain.btnPauseClick(Sender: TObject);
; V5 g/ a; S; z begin( ~5 I" J: L" }, ]7 D1 j
with FISpeech do
( Q8 u; n% \3 `/ l9 e4 I2 G if IsSpeaking then5 x3 k* G% [2 v
begin* |7 ^, }% c4 p) ~0 k
AudioPause;
" k# i! [/ `, p) |; A0 _ btnPause.Caption := ‘ 恢 复( &R)';
$ y( d8 B' h/ N" R( R9 k: Y* v8 t end- H6 u8 f0 S8 D
else
5 J8 J. a2 _1 [" K: { begin
5 G% S, t: O5 H# \ AudioResume;
- m! `, h6 }. _0 N Y6 ?( L btnPause.Caption := ‘ 暂 停( &P)';- g7 r$ v* n& v; p' u3 f+ Y% z
end;, i8 z4 U- d+ L! W3 z
end;
8 k8 y3 s7 w, E...
, T" r$ n1 ?3 t1 Q( R0 d6 p----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 . e W2 {5 p6 Q. @ b
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 * } n! c* ~+ ]) a2 ]5 @& f
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 4 e; `* s% V. N/ E& J1 d, E
...
! o6 u( Q9 G3 `IVTxtAuto = interface(IDispatch)
$ u' H: i0 y! O1 a% J ... _( C g* C$ ^7 f) `
property Speed: Integer read Get_Speed write Set_Speed;
+ @+ n. G/ M5 Y5 [ P property Enabled: Integer read Get_Enabled write Set_Enabled;
+ w( E1 O/ [* L% D- G ...' u6 u8 E8 U0 i. j3 ~ I
end;
0 [, b$ G( `4 {3 @& ` ... 0 F! Q1 o( c; k& o- S# d8 D
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 & [' s# _' j) o, g1 Z( J6 Y6 ?
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 ' f2 R% f$ [5 x3 B
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。5 j1 B* G/ O& }( F' ]) Z3 { ?! v
0 t% E- _+ f4 y+ I; s3 h |