|
- y' T/ x d% D b
华 中 师 范 大 学 卢 小 海(flier@126.com)
$ ^1 t, [) h/ ^! }6 n5 c6 m 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 * T* h# L5 D* f- o. D: l
, W0 ?5 ~2 G: L4 y3 p ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
7 U6 [2 d- g8 v [) t4 ]/ j" ]1 `----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 " c3 b/ |( [1 `5 n1 H9 x
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 ( X' V, g' O0 l
----再 在Delphi 里 新 建 一 个Application。
2 @/ G D8 y3 l% T* p; D7 n8 B----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
0 ]% y! }0 u T* N. V----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 0 H [, E! ]0 D; r6 d7 D
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: 9 h. g" p) S( }: O
...8 Q) f6 W0 }! E# y( E f X# \
procedure TfrmMain.FormCreate(Sender: TObject);0 h% _* Y# t* e/ J) ]
begin
* a% |6 V" m; X* ]9 X FISpeech := CoVTxtAuto_.Create;
3 h2 L+ o, \" u; [ FISpeech.Register(‘Demo Site', ‘Demo App');
. ~8 }( I3 v2 ~4 u9 E end;
4 N ]6 r/ }: Y' V3 o! p6 p( p: n5 |) y...
) Y5 A& z$ v+ H# G" [# ~----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
) I; _2 e3 H& j0 Z4 f! c8 C1 P----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 6 d' |( |0 e; a f: B
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
- F' I/ T% V1 O9 hForm 定 义 如 下: # Y# c& z. V4 o6 V
object frmMain: TfrmMain
! E/ q* e( L8 b$ j& l- \, C Left = 296
% O+ M" ^7 O# u/ [ Top = 187- } x1 z: `7 v; J5 H2 g" ]) ?8 T
BorderStyle = bsDialog
f' E" _+ V. X1 x- Y4 @ Caption = ‘ 英 文 全 文 朗 读 演 示'! E! v& |% ^* @$ I8 W
ClientHeight = 185( {' h, |% b) X
ClientWidth = 456- `$ ~; ?. W: Q- i$ A2 Z, b3 |
Color = clBtnFace9 w( ?' v# j9 a! s( y
Font.Charset = GB2312_CHARSET8 i% V* `8 |4 I3 Y6 w- ^4 T* a
Font.Color = clWindowText
0 F& Q) o5 C3 s3 W9 w Font.Height = -122 q# m5 l1 d' @+ ?5 M, o; ~! B
Font.Name = ‘ 宋 体'4 d8 T1 `8 a- ?% g' z8 R
Font.Style = [], f' g% R- g0 B
OldCreateOrder = False% G9 | \7 i. _) v
Position = poDesktopCenter
( y6 V, G6 m- K OnCreate = FormCreate" R/ D5 K; K, z
PixelsPerInch = 961 V& y7 [1 h+ r
TextHeight = 127 `4 d% O# c" @; J" z3 q
object memText: TMemo9 y, H) _& F. S: l% l# w" f" s
Left = 8
, _( Z, f! S4 _2 z Top = 8# \: z# W! [2 D2 ]
Width = 361
8 B! P3 B+ j3 z Height = 169
& B, e7 O8 m2 e! w+ Q ScrollBars = ssVertical
' H+ [$ X/ Y( {6 @2 S- j+ Z1 ^ TabOrder = 00 T2 U! d& a, c& ~4 V
end
: F5 v* v( N$ D3 n G. |1 V5 C object btnRead: TButton9 ~9 }4 ^, u0 u0 {
Left = 376% [/ Y% a9 D& m8 W( X9 q _
Top = 8
! Z1 K! @: e! u3 ~: ^, f Width = 75
# \5 r3 ~. N9 z# \1 J1 } Height = 25+ O3 i# h3 J: C: @( d
Caption = ‘ 朗 读( &R)'" z2 A5 i: i/ d# ~+ j f
TabOrder = 1& N( m8 R5 ~) Q0 v6 D
OnClick = btnReadClick9 L" M' W& d9 r0 b; y7 g
end0 ?* m% n% m) q& }
object btnPause: TButton
/ n( Y: v- C& A) _6 P% M- C Left = 376
j2 `6 t, ?# b* |8 s Top = 40
- _0 m7 s' |( F Width = 75 Y) u; r5 E/ O* ^- e
Height = 25
0 t0 S8 L+ S' N q) Q8 R Caption = ‘ 暂 停( &P)'' t: `) O3 ]* q' p9 ?
Enabled = False
3 R2 c3 i5 \+ H3 p3 I2 K. s w TabOrder = 26 ]: Y8 D1 v4 ?+ V
OnClick = btnPauseClick
( c; d: _' ?( ^ I( X end6 Q' v2 i; K1 U2 V2 P1 i
object btnStop: TButton
, _2 i9 [+ p$ p, O! [9 } Left = 376
" R( z6 o8 N& K" B8 l- n1 z8 [- L Top = 72
8 v/ I2 c+ ^3 b: J9 z+ g* D Width = 75
6 R% A- C1 u8 Q, V9 ? Height = 25
4 T" v1 m" i" k Caption = ‘ 停 止( &S)'+ n4 ]) a. H0 C
Enabled = False
3 e) M- Z2 j. F( E6 Z& b TabOrder = 3
2 e# z7 D% g4 c) q: i! [. a& W OnClick = btnStopClick9 _. n8 G% {; m- \8 z; F. O
end
l* R; Q7 d& P1 D# Q d object btnForward: TButton/ k+ i. _1 \( h0 O S! N; e
Left = 376: c3 I7 M, j% N
Top = 120/ ^7 ^8 _4 a5 g1 l
Width = 75# }- R) F, F' ]
Height = 252 f8 u8 R6 Y0 Q [1 w
Caption = ‘ 下 一 句( &N)'! M+ D* h0 S- x1 K) I
Enabled = False
% m! l) [: S# V8 Q$ S3 A, z TabOrder = 4
% |- \, r d- k& w: `6 q5 } OnClick = btnForwardClick
p) O& Y1 I9 [- { end" H/ o0 W$ \) m1 Y' o' F1 R8 s. U
object btnRewind: TButton
' e0 v5 p2 U1 E: Z$ w4 l0 k Left = 376
( ^8 @; }+ [& V2 P Top = 152
9 C- n( T0 Z4 l0 M3 T Width = 75
; @- P) f4 D+ @) T* f5 A Height = 25
' }- I/ u* p- w" ] Caption = ‘ 上 一 句( &W)'
7 \, [8 |0 P1 w t/ _: w' x" d5 d Enabled = False
# Q" F3 { B! q6 g' |" f TabOrder = 5
9 w4 p/ ~6 z; C) t9 F- y, \$ c: T OnClick = btnRewindClick% D8 b1 C7 j& g% \+ A
end/ g! U+ x/ |7 A6 R9 c# h
end
6 e' s- F( D. D7 Y n) g) R- K----关 键 代 码 段 如 下:
7 \! f. L9 M9 l6 ]) \8 H---- 1. 朗 读 与 停 止 2 w* w; `4 L% i9 L
...
1 W3 d7 ~2 K0 \& o7 p3 Rprocedure TfrmMain.btnReadClick(Sender: TObject);; Q$ S0 ]" d8 L) }' @
begin
% P" L( q( ~6 f( E& h0 ^3 u FISpeech.Speak(memText.Lines.Text, vtxtst_
" Y: H0 w7 s1 ` h) [# e3 T6 O: wREADING);6 e) j9 c; o3 S3 r/ A
btnPause.Enabled := True;( I4 v7 I8 E* z& \0 U, G6 V: v' v3 r
btnStop.Enabled := True;
1 A7 P o+ ~. g2 q0 ~" ^* R end;- b3 W& ^! _- J ~. h* A8 n l" k
" P1 [1 U6 ]* P( L& |- N; J
procedure TfrmMain.btnStopClick(Sender: TObject);
, v1 F- g1 R S, ]5 @4 [ begin
3 q/ ]/ ?. O: D6 t/ ?* z) t FISpeech.StopSpeaking;" D6 W8 O- a9 w8 Y- H3 e9 T
btnPause.Enabled := False;! A: |$ p! f( i7 a4 a
btnStop.Enabled := False;
* h+ H0 f$ n# H7 {. p3 i btnPause.Caption := ‘ 暂 停( &P)';
1 f9 Y! Z5 @; e0 l6 _1 w! Q end;
$ T* M2 n% `7 |' N; Y3 r2 }, ^ ... 4 ]7 _8 f- ]' ?) V4 v- C
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
/ u/ B0 S3 |, d" K- u
+ N: [( V7 w& M; w---- 2. 暂 停 与 恢 复 ?& O7 @1 G1 \2 `1 z6 h# Z6 q
...
6 C ]- ?( W4 i: }5 P' Gprocedure TfrmMain.btnPauseClick(Sender: TObject);+ ^2 b* I1 L4 i# d# y6 Q9 w, @
begin1 E) }7 x; G( _+ J" m
with FISpeech do
B) `0 @, N; Q/ I6 {+ ` if IsSpeaking then# ?, D' K3 I8 W- J
begin8 Y# V9 q' ~' w* J+ ~7 f
AudioPause;
- @1 B' G( W; L btnPause.Caption := ‘ 恢 复( &R)'; w o1 c6 P9 }7 J
end
3 t" i) j% k' R3 y! ]6 o) ?- u- f else! }4 x3 b3 h" I$ R2 t9 Q9 K1 r4 @
begin+ b1 Y- ]) k, P7 o% M
AudioResume;
- L8 q" ]- P- H) J9 p" v" Y& u btnPause.Caption := ‘ 暂 停( &P)';
, Y$ b, I/ j/ K" \. Q( B3 k$ ~ end;
9 f' I" g' C/ ]' u4 C" Bend;- K0 w$ ~# A2 g! M* A
... ' e# a0 I6 B( D6 X
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
3 N" {! ~; u7 _( b0 T( l----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
/ @( B7 l& b1 F" W Q9 u1 {----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: % c: |2 F6 x4 ?: t" m
...$ F9 c) l4 r; h1 A% j
IVTxtAuto = interface(IDispatch)
! {/ e7 l* M" ^5 ^: p8 N ...
* Z0 r& t/ q E$ n' Z property Speed: Integer read Get_Speed write Set_Speed;! C: K: ~6 H9 t2 G# ^) U
property Enabled: Integer read Get_Enabled write Set_Enabled;, c$ ]' ^% f5 V6 M
...
# l; [4 B3 ^/ \; M1 Y5 R( Q% C+ |end;8 L. H- _( d. w2 V
... ! l# O0 |: g Q- e$ H
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 . c4 _7 D7 y) O. m( ]5 ?6 a* z. ~0 \
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 5 m# i2 \+ m- u, M4 N5 O- D/ M5 i
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。, d6 t9 Z1 z5 V8 I
$ q* w0 G5 o0 c, t; w4 m
|