|
1 W' [! h! ~9 b9 ^3 U: Q7 x
华 中 师 范 大 学 卢 小 海(flier@126.com)
_5 s3 A9 p- Z, r! ]' ` 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 7 l; I3 N: C# g% y2 @8 c8 E3 t
9 J. C; ^- ~ Q# v/ a% n ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 - g U# R$ g. g
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 % T) g2 g; c, T$ S7 }
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
" k3 V4 ~7 `# }----再 在Delphi 里 新 建 一 个Application。 1 |8 ]+ |8 [ c8 k2 t8 r T
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 * E j; \& E) [* N& K, W
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
a4 M; J7 }6 L# E) ?2 l5 Q/ |- \----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
8 {% D: k b' ~# [7 f' J& E! W7 H ...
9 M( u) I0 Q3 L procedure TfrmMain.FormCreate(Sender: TObject);
! T# m+ n; J4 q9 q% N begin% o7 R# H- b+ }8 x& S3 I$ A) R
FISpeech := CoVTxtAuto_.Create;
. i3 L4 k8 r( ?1 ^ FISpeech.Register(‘Demo Site', ‘Demo App');0 B: d3 A1 d" e0 T/ z
end;1 Q" p1 K" m2 |, m& ]! M9 e
...
' _, f. w! L) r% Z----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
, X4 l" C4 d0 K2 C+ M----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 . b% L8 v/ }- P" e4 \9 S
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
& A Q+ e8 c1 a0 g* a' RForm 定 义 如 下:
& [3 \3 ?6 j3 l& Y5 s: t @ object frmMain: TfrmMain; R! H: T( `* }6 k2 M8 R
Left = 296
0 E; {( ^" C! I6 W; Q Top = 187
' B* H6 c, l G% J6 K5 p BorderStyle = bsDialog7 q5 n/ T) `+ w8 k9 V
Caption = ‘ 英 文 全 文 朗 读 演 示'
U) I; \: d. [8 t4 v; U* H ClientHeight = 1850 r; v0 E" N6 k% H% H! n. {
ClientWidth = 456
% |% Y7 m; h5 [& l' m3 f Color = clBtnFace) M& C9 X- ^. {4 M, M) |+ r! H i$ S
Font.Charset = GB2312_CHARSET4 s" y- g/ T9 w
Font.Color = clWindowText) n- l8 O! Y, O/ l0 K+ f
Font.Height = -122 U' T! j& p8 K1 S4 N
Font.Name = ‘ 宋 体'
. W' G$ Z% S8 D/ f: Q/ Z1 `: ]9 r% \ Font.Style = []; _- O7 j. x/ _" v) O
OldCreateOrder = False
9 ^7 i1 l2 \: U2 o' y" B Position = poDesktopCenter
; F; }/ s& v& T" o8 B5 | OnCreate = FormCreate
' b9 Z1 O. U; {3 j9 N PixelsPerInch = 96- I' S* k0 A. R" w8 P
TextHeight = 127 A' S: p5 a! X% B' O% q* w
object memText: TMemo1 @2 j1 O8 a! Z1 S* i' w
Left = 8
( j9 ^2 D! w( i B' |! i Top = 8# w2 i1 [8 Z+ l. P" Y, m0 P
Width = 361# V- R& q G" r& l# x I5 E
Height = 169
4 ~- v6 i2 W) e- R6 `$ V) D ScrollBars = ssVertical
E: g W' D% S" h- m' E2 q) q TabOrder = 0
5 ?0 g+ m% s! Q0 [5 L) P. N end
; k9 a9 h& I- j) J$ T% M Z; h, ^ object btnRead: TButton
0 E5 t3 ^% T' Q9 r2 J Left = 376
: _+ I+ d! [4 ]5 T Top = 86 [9 E2 d, |- s
Width = 752 X8 F& x. ]4 v. c9 t
Height = 25* i5 B# v: U$ V
Caption = ‘ 朗 读( &R)'
) o: v- \ n- m% ^ TabOrder = 1
. b u6 M3 B1 f. X* O, n+ E OnClick = btnReadClick
. ]* B: o* \- Q# b end
; G2 v; i4 h# N/ T+ ]. P. n object btnPause: TButton) a( N, N" Y; Z& r0 `# l. i
Left = 376
! E, y8 w, x/ h+ D) D& W Top = 40
) E: A( X P6 z7 ? Width = 75' `2 I/ e2 m( h: }0 @, @ I( `' F
Height = 254 |+ M/ a) U, o( @0 n- Q. n
Caption = ‘ 暂 停( &P)'
5 K2 _( B% J& K0 X, C" b Enabled = False
$ @- w' G/ r4 d TabOrder = 2
1 H1 \- g. A: w* J! O2 { _2 U) @ OnClick = btnPauseClick$ h$ P0 [1 R' ]# ^
end
, w1 E' J/ O+ b4 ` object btnStop: TButton
4 j# Y3 G# A) M4 o; b4 W6 y" G Left = 3769 W- K. u y5 k& \6 z5 h
Top = 72
; R& p% V( d/ F0 P2 r; q9 L Width = 75
2 Q0 W" Z& y0 z" V$ K& `$ ` Height = 25
* S1 d, A# C" W3 j3 }- C Caption = ‘ 停 止( &S)'+ r2 s+ F4 U7 U. y: V6 B
Enabled = False
' `, c; S: k* u3 i/ e TabOrder = 3
- \8 K1 I3 i' g; n5 t% W OnClick = btnStopClick) e3 w* v' b5 Y8 }! x
end8 V- j: @0 f7 u |! G4 S
object btnForward: TButton4 q4 o% ]& G" r# d5 }+ ]
Left = 3766 f# z4 W% W% K
Top = 120
. J S# Y l$ A! R Width = 75; B% e' G* w& T& n4 p4 B7 `
Height = 25
7 }0 n' Q" |; S# V Caption = ‘ 下 一 句( &N)'
9 f) e$ X- d8 _ Enabled = False T6 R8 P) |. L( a) W$ {+ s
TabOrder = 4. U% S. w0 U+ W! M
OnClick = btnForwardClick9 E! ]3 t1 d$ t' _5 ~( Z# h
end/ ~* F) A7 f8 b5 p9 Z4 A2 v
object btnRewind: TButton+ Z. Q7 ]- m% `) F
Left = 376
4 |! g0 F# M. Z+ O! a Top = 1526 V2 f2 m1 t" ~
Width = 75
" e7 v, P, e2 U- G1 o3 L Height = 25
4 v# F: m% V. j* @. W/ o) Z Caption = ‘ 上 一 句( &W)'# b6 V2 g- ^0 }; P/ w( J
Enabled = False
; V" n, n" Y- k0 { h. { TabOrder = 5
4 D" ^+ j5 h! f% b OnClick = btnRewindClick
2 S) p6 o P- o% _3 @% g) } end# l% U" c) K2 o- U! {! R7 s* X
end
+ J1 E. m& ]8 M/ r' o- F) s+ E----关 键 代 码 段 如 下:
& ~. ^# T6 g: ^* K: ?$ n( a---- 1. 朗 读 与 停 止 ; q2 V% e2 J ?3 u' j" p* I" A" X
...
4 _6 q5 i; p8 oprocedure TfrmMain.btnReadClick(Sender: TObject);' d8 ^2 f% X; Q8 v
begin3 h. s! [1 _. v, A- @& n4 y9 h
FISpeech.Speak(memText.Lines.Text, vtxtst_ ) F% H8 E4 X5 a
READING);: c+ e1 E* b. z% W3 O* c
btnPause.Enabled := True; R: F: j- b2 E3 Q
btnStop.Enabled := True;9 \/ W' h5 G* Q, m0 V0 {2 j' A% m
end;" E; O/ r0 |2 `+ V! U( u
6 U) z+ [. b# v% P- g! N
procedure TfrmMain.btnStopClick(Sender: TObject);
7 e& y* y( o# e* @! [( A begin
( B: u; W N& {- Z% @! @7 w; g FISpeech.StopSpeaking;
( j9 o$ S \, E0 \3 K6 X' ^ btnPause.Enabled := False;
; [& D5 _) F0 ~# d/ B btnStop.Enabled := False;+ b% T" v1 m, R% H- O* K. C, {
btnPause.Caption := ‘ 暂 停( &P)';, d& \6 x1 I7 V. ^
end;
9 N3 {7 N. a' ^5 K4 k ...
/ N3 U$ B% _# t----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
u" I+ Y/ M8 R" X2 c) c2 K Q* X9 o' d* r
---- 2. 暂 停 与 恢 复
`% v1 _! J; Z$ O" |, y! r0 }, H: }1 f ...8 V! a y- a6 S) d: G) y+ ?" J, g
procedure TfrmMain.btnPauseClick(Sender: TObject);% h2 N+ r: }" }
begin9 O) Q/ r2 e1 q/ @, S" e
with FISpeech do
( B3 M7 x! p5 @2 O if IsSpeaking then
+ w% A" S+ T: ^% |0 p) w, d begin# \6 }6 J+ M; n/ _/ t5 o1 h
AudioPause;- _$ A& T* b: {$ J
btnPause.Caption := ‘ 恢 复( &R)';9 J: `0 G8 n G& h
end. I+ I4 K% i* N9 \& g! `5 v
else% \0 J, F* X1 G( j% e
begin) r; ?2 p* U( t# O. h. \0 ?- d
AudioResume;
7 z/ c2 C5 G7 E6 k6 d+ `5 ^) t btnPause.Caption := ‘ 暂 停( &P)';" Q* L/ ~7 \# A! f+ p! |2 B
end;2 {7 Q3 k) n# ]
end;
% e, V6 t( _) l... / E% P: o1 D m2 z7 ^. S
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 ( D& s# B9 g; Z; E- J( Z" @$ K+ I; P
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 8 i1 z) U, A: z
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 4 C" E2 {1 e* q* M7 S8 N
.... {3 j1 H2 z; m* t7 j: D0 m4 [
IVTxtAuto = interface(IDispatch) r# x$ O) t: d
...6 _, l/ K0 z6 B! w$ v$ p( d1 {, [
property Speed: Integer read Get_Speed write Set_Speed;
, S' g Y! L! t& _4 N' B property Enabled: Integer read Get_Enabled write Set_Enabled;
$ B/ f3 Y+ m, {8 ~ ...
# _9 @& S# `, X) B, v% cend;: N) e, a2 U7 D) W( V+ }4 L
... 6 K: ^4 U+ M) ?: o$ A$ r
----即 可 正 常 使 用Speed 和Enabled 属 性 了。
; O. @$ R, j* C$ P8 k6 `9 O- G* e----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 : Q8 d Y! i0 X: v
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。4 p5 z1 f1 [) J8 w
3 V; [' g% X6 g& t8 h
|