|
5 o% T2 O4 C0 a; h& c) O5 z
华 中 师 范 大 学 卢 小 海(flier@126.com)
$ |1 N4 O+ U o/ N. P* k; F5 l/ U 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 * u+ _, B7 y' w/ k: A2 E9 }; E
# {0 |+ r$ ~1 V2 S ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
1 q H$ N) L( Z/ t' z----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 ) G% S8 O- J _1 Y
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
2 q" W' `5 L S$ j7 a0 f7 [0 O' h) S----再 在Delphi 里 新 建 一 个Application。 " O' R& l5 y+ j* T. V$ v4 A
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 4 k* s- H6 w: x$ q
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 ! t: H; t$ u; Q2 @* V! ^) Z
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: * @" i# j q! h
..." R9 x: h8 y# B( X% s' y# \ Z
procedure TfrmMain.FormCreate(Sender: TObject);
9 U$ H. V9 G- s begin
3 @: l" J, k5 t6 O FISpeech := CoVTxtAuto_.Create;
$ ~- J% T2 d; q1 \( o9 Q% H FISpeech.Register(‘Demo Site', ‘Demo App');
8 p! m2 f6 v" [ end;0 O9 f5 n% K' ]! u& m
...
0 M9 m! ]+ }0 B0 T----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 3 u2 W2 q# \! r1 ~/ E5 n- J3 G
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。
( @' a& y% b4 X2 i" ?2 _' p: X% I----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
+ D/ U+ x a% _4 P) t" [* KForm 定 义 如 下: . J: S! h3 c5 H* r) S" i- F
object frmMain: TfrmMain
: l: O% J- r( @/ ^0 q2 T Left = 2963 t' w% Q8 z+ o, M0 J3 C% Y3 W
Top = 1879 }; t ~$ R- n! a, w* W: ^
BorderStyle = bsDialog* C! A2 o- k$ E
Caption = ‘ 英 文 全 文 朗 读 演 示': V1 X9 W0 Z0 L0 ?2 v$ z e! B
ClientHeight = 185
# h: I$ ~% n9 ~# q% b7 i R ClientWidth = 456" I; L; z* p9 b5 x8 r7 ~. A" ]
Color = clBtnFace
( O- L7 i' w3 V) Z2 V7 J. i Font.Charset = GB2312_CHARSET
8 A' ]$ O3 C/ i1 U0 h& w Font.Color = clWindowText8 f. n4 T. v9 C
Font.Height = -12* O& E! A8 ?' I' C. H7 Z7 c. ?. R
Font.Name = ‘ 宋 体'
: Q3 e$ H# s* M& Q$ F" W7 y2 S Font.Style = []
; \$ @6 `$ J. l. p4 t OldCreateOrder = False
& c, H1 t2 p- k# ?+ X2 q2 [ Position = poDesktopCenter* v, j# x4 J; c& Q
OnCreate = FormCreate/ _# H; A# m5 v) x+ B( S
PixelsPerInch = 96
; ?% x" C0 M0 L& O4 c" c* ^ TextHeight = 12
9 s4 F+ j7 s# _; r9 ^2 t! D% b' @ object memText: TMemo
- W) X" P* k( O4 S0 I S4 B Left = 87 f6 c) N$ [+ h$ D
Top = 8; E' R( @4 o, T* O0 v! K
Width = 361
! i% f8 z& w% I, P! S) \ Height = 169
( b, a- Q1 g6 j! k ScrollBars = ssVertical% c8 u3 O% _9 o4 o; i
TabOrder = 0
; p, x7 p* U. P7 ?. v" W; N end6 F! k+ B/ l$ U
object btnRead: TButton f$ a2 \8 L) o
Left = 3769 }/ P9 X/ r" s0 h$ N
Top = 81 h8 y/ q& i, C4 O; W( L& z
Width = 75
% F% {/ i: b, r* @' R E* J Height = 25! m; `, n/ Y9 W$ M/ R+ ^
Caption = ‘ 朗 读( &R)'
6 Z3 c" u& z/ ]1 S TabOrder = 1
+ L7 T4 ]( T! ]) S L) k0 T: u OnClick = btnReadClick
" O" Z; U+ q9 x" K7 ] end0 k/ G& R M5 y! Q4 x
object btnPause: TButton3 x' p: M+ R) W+ |9 r
Left = 376/ m% s. J4 G% ]! J
Top = 404 d. ~# i4 {& |5 u4 ]% K
Width = 75
% _4 |7 w/ a9 m& o Height = 25
& C; P J W+ g0 ~$ j5 k Caption = ‘ 暂 停( &P)'1 z. ?8 h5 Q* {# U- Q3 I
Enabled = False
) C, A% F. {& L" g, T( ~8 t TabOrder = 22 n3 v! g: y. c4 o0 W0 z# ?
OnClick = btnPauseClick( G1 e2 _9 a2 M# [" x
end/ |6 P4 _4 }' `" h$ N; s
object btnStop: TButton0 ~" r5 M5 {( ?# U# L) R
Left = 3765 T5 I3 o! Z, o( u$ n+ v
Top = 72( e ~7 b/ @1 C( A$ t
Width = 75
5 G, _. ]& R8 ? Height = 25* ]- h/ N' ~7 Z% U5 E' N5 f$ p' Z- I
Caption = ‘ 停 止( &S)'% I( l% S# m: ^, k
Enabled = False, O* T! v1 O; {! J' y; k
TabOrder = 3
( r3 U' N* ~) x- I+ ~; ^ OnClick = btnStopClick
. h8 z8 U9 m! n' q) C7 ]% ` end4 X6 S" v+ V# E% A3 [; {) m' ?
object btnForward: TButton
6 X: d/ `* l5 m Left = 376% R) ]6 C) ^. h, N! s j
Top = 120
2 E* u, V3 @7 @9 ^) I Width = 75% j* t V0 @8 q; x& G4 ?( k+ ?
Height = 25
' D9 w( y ~/ H4 I0 @3 Y Caption = ‘ 下 一 句( &N)'
5 u1 f x; f) a4 ` Enabled = False: P$ X5 o; c# A" L% R: Y
TabOrder = 4
# w2 y4 O2 Q/ K. a8 k OnClick = btnForwardClick+ a+ Z' I/ E: S) S4 H b
end) i2 x+ U. _( N
object btnRewind: TButton
# ?- y$ l$ Q/ m' Z) i) {' E Left = 376
; D; \0 }: x4 M) x Top = 152
: G5 Y% S. G, Q: h. {1 \ Width = 75/ ]2 e7 t2 `5 |4 E8 q6 _, d
Height = 25
( r1 C# F% Y" J Caption = ‘ 上 一 句( &W)'
6 w" Z; w5 n& x& f1 e; ` Enabled = False
% Q+ Y( L6 ^5 s l$ i TabOrder = 5. p9 D4 q0 B0 P' p& d' r! i
OnClick = btnRewindClick
! @0 [. N9 s( a0 W$ x. J: _: f end
4 [" \% U B/ P0 N$ n end
8 ~8 A8 y4 x- ~. S/ b' `----关 键 代 码 段 如 下: ] H+ @3 B/ g+ `! `- B, a
---- 1. 朗 读 与 停 止
; k F/ ]. |( e" t" R4 ^2 ? ...
U. g: w- @7 ^' Z4 {. e' ^+ kprocedure TfrmMain.btnReadClick(Sender: TObject);7 k4 j7 Y* Q; s- s
begin. l. U. ^) e- C
FISpeech.Speak(memText.Lines.Text, vtxtst_
B8 O% F( M0 Z8 PREADING);& Q, x- G, _+ W) I
btnPause.Enabled := True;
% z+ @* F( _2 Y4 @% a5 H0 Q% e btnStop.Enabled := True;- N! q" K; y/ Q; [
end; f0 t0 C- E* L: Z. I* d
. n2 t; w5 G( o) S) S6 Z9 v
procedure TfrmMain.btnStopClick(Sender: TObject);
6 u1 c9 N# C+ ]0 d begin* o# B* H6 C$ R% M
FISpeech.StopSpeaking;; {% e, k1 Q+ y+ W) {. W- U
btnPause.Enabled := False;8 G# y% _5 S( h3 A8 a; @+ t
btnStop.Enabled := False;
( Q) ?% M3 ]$ R5 `& p7 H btnPause.Caption := ‘ 暂 停( &P)';
8 \8 f5 @7 e, S/ I1 j% Z4 f end;6 O8 c) v9 } }+ v
... + F+ [7 f: [% ?. u2 n: [- n
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 2 D1 y1 H& A7 n0 E0 I3 n& b: C, }7 ~
7 N+ {2 W2 s# }8 G, ?
---- 2. 暂 停 与 恢 复
7 M D# U3 b( a3 @5 N! V ...
* I- [9 }) A( hprocedure TfrmMain.btnPauseClick(Sender: TObject);# m" |, Y& R9 Z8 o0 q) Q* W2 V
begin
" A2 W6 ^6 G: c2 ?0 O. { with FISpeech do, ~+ y: |" W8 a9 _. \* J
if IsSpeaking then" m; L9 H8 [! k# l4 E* p
begin
4 |0 S$ {! j# W( h1 K* x$ ~: _ AudioPause;
1 f3 W% L& w" C1 ]8 W btnPause.Caption := ‘ 恢 复( &R)';
3 P% d7 H7 y" ?! O5 @ end
+ G2 _/ J/ i# p p2 T9 X$ f8 i else
2 G4 Z: @- w W. A/ N8 n begin
, e5 P& a+ {$ F: Z AudioResume;; }6 y) ]+ f0 a9 v' Z
btnPause.Caption := ‘ 暂 停( &P)';
7 M6 w4 M# R, X0 e end;
" q$ F; u3 V5 {5 @end; z N) n3 Z9 [5 D! Y
... ' z" E( N% o6 C2 C# l
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
; a8 w& Q3 m0 ~# [----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 / I B, C& E" j8 A P8 F2 t
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 3 H( }& D b$ g9 Q# }/ v0 v* K6 u- c
...
; J; ?' Q+ e6 X. Q2 BIVTxtAuto = interface(IDispatch)
% v5 M+ g/ A) M; W ...6 I8 M3 S* W" V4 n1 E2 f% l
property Speed: Integer read Get_Speed write Set_Speed;$ x2 k0 z& M, H3 ?# {; `$ v W
property Enabled: Integer read Get_Enabled write Set_Enabled;9 P+ O! o2 d7 Q' I. M$ i
...
0 Z; R% |# D& P, Hend;
' R( i3 O, f7 Z ...
, O/ F6 T1 K) a6 L/ k5 W! P----即 可 正 常 使 用Speed 和Enabled 属 性 了。 ( @+ g; j. C" V0 E. A
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 1 E+ j& b1 S+ N+ U- h: C
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。. n4 j% O. q2 D
. i$ t# I2 @+ t7 ^# u0 O0 L0 y
|