|
* A- M% v0 f7 B+ ~1 e: _( Z! S
华 中 师 范 大 学 卢 小 海(flier@126.com)
6 n$ z" D) _3 P4 j. l$ C 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
: b# Y' Q5 `! E2 ^
$ p& \2 O! g: D# A' o ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 2 g$ \7 U' [0 W3 q- }% U
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
" Y1 A3 Z7 @; m. S- F----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
9 \# Z4 ~% @0 O8 Q) q* H) s( o----再 在Delphi 里 新 建 一 个Application。
\0 n8 Y6 I( Y----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
Z2 h5 b$ n* N; b1 Q5 I* y$ ~; Z# ^$ L----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 - y4 | B# o. L! Q/ N ?9 v
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: : e m U8 z9 e6 l3 ~ e- v
...2 A3 x# d' h" A
procedure TfrmMain.FormCreate(Sender: TObject);. N0 m5 Y/ q. E) _4 I) k1 i
begin
9 D9 y6 S( C8 N2 A8 n- s FISpeech := CoVTxtAuto_.Create;& E- Y4 i$ i/ t0 K
FISpeech.Register(‘Demo Site', ‘Demo App');
+ Z3 M7 L' W+ ]& ~ end;
* h5 j; D- j- ]0 l...
0 m, w, l/ y" j+ ?6 N) b----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 " A( _! l- j4 q* J5 A; f# I+ T# n5 q
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 & L6 R. R5 f9 j$ C; S' p- h; \
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 9 ]7 Q) ~) ?9 |) e* K. K x
Form 定 义 如 下: $ O' i% C) r" \
object frmMain: TfrmMain5 \/ U2 k- Y) x o& o
Left = 296& C4 u) _8 F6 Q4 L
Top = 187
1 D2 j5 E1 Z4 H) J BorderStyle = bsDialog' u! X2 x/ d2 V% U8 s' ]
Caption = ‘ 英 文 全 文 朗 读 演 示'- D" T6 ]. X# w
ClientHeight = 185* R+ a5 q3 j! ?6 c- q* y! ]
ClientWidth = 456; I( i7 o5 k; |( o6 F' L( ^2 G
Color = clBtnFace
- K) t/ J+ c: P4 J3 G! m" u Font.Charset = GB2312_CHARSET
& ?, V3 P! g! q3 O& H7 d3 b Font.Color = clWindowText
% X" z2 n! [2 D4 S, U( C6 | Font.Height = -125 u) _7 e$ P5 W! X0 R5 S
Font.Name = ‘ 宋 体'8 Z* {+ u4 c9 ~- @6 g
Font.Style = []% O2 s) ^& Q, r( h8 C* y+ v! ~, S
OldCreateOrder = False
E% Z( P# e4 s6 b3 V. X Position = poDesktopCenter
9 Y. `8 ?8 `+ G OnCreate = FormCreate
: W+ B; D" d# }. O# b8 I0 N PixelsPerInch = 96- D" X! Q7 i5 C: M* ^ y
TextHeight = 12
( {, q% [# Q+ e; S4 K object memText: TMemo4 L( C5 [0 e8 T9 v3 M& F
Left = 87 N& g" y) {0 s
Top = 8
8 f; `1 O4 m T5 j4 m+ S7 G9 i Width = 361
; B* s( z* ~* ^ Height = 1699 H1 h- ~3 i- e3 W8 C9 S8 K
ScrollBars = ssVertical
9 @# W/ z) t: Y' @ TabOrder = 0
+ C2 n) _1 Q) r9 u. U end* Z: Z1 |( v# C/ D
object btnRead: TButton0 v8 N& L- ^3 k* V
Left = 376
3 G; q0 v: i# d) x' L2 @ t( m0 G' q Top = 87 W/ {2 B8 w3 |/ d: j* Q( S
Width = 754 N# ]4 ~- o: A" N# q: g
Height = 25
6 t# d6 o2 Z. l6 _ Caption = ‘ 朗 读( &R)'
! @0 F( Q( _; d/ @9 W% u TabOrder = 1
, k( K( y$ E6 M OnClick = btnReadClick4 ^& J. N" X# _9 u2 R7 x; O5 S
end* C: b, N/ x' C! ^9 F3 t
object btnPause: TButton* m! J6 S- @) \1 B( W
Left = 376
@; b- k7 A3 s6 u# Y' j- ^2 O Top = 403 H; P5 I# {+ J* e( O
Width = 757 I: n3 {4 E" U
Height = 25
0 {& A1 C7 i6 g% O Caption = ‘ 暂 停( &P)'& B# n! _, X2 G$ ^
Enabled = False1 Y: Q8 @( b, a/ v: y: X, k, i
TabOrder = 2+ i, L1 [, H3 p1 D( W" j/ t5 s
OnClick = btnPauseClick- A9 C7 P3 }6 L: B+ X8 @* O
end9 L9 d( l( n9 L6 x' j
object btnStop: TButton0 u7 g7 z* H& C$ @1 B& r- \ k, N
Left = 376. N' E6 L, r% p- a$ T" e
Top = 727 I& ^4 ~& v- Y0 Z. }
Width = 75 R& L$ s( a9 ]$ R j8 j. I
Height = 25 x; {$ M& ]& M$ Q5 M
Caption = ‘ 停 止( &S)'
6 o" H* m3 E5 i. y1 p# A# Z& z Enabled = False! S2 z# n/ M1 {" z2 }& w. d0 P' Y
TabOrder = 3
9 V) ]( T9 h) h OnClick = btnStopClick2 v+ p# W3 V# O( @9 |
end) s% a) E+ @1 I
object btnForward: TButton
$ y, R7 O5 e+ h; J) v+ R0 N/ H8 E Left = 376
6 e/ Y4 [) ~: V2 j( I2 n7 f8 \ r Top = 120
! A# |2 m5 ?3 J4 @3 N2 U Width = 75' A1 G Z" F$ a m" V m2 X& a3 ]
Height = 25
" X# G# |) c' ~& r5 r Caption = ‘ 下 一 句( &N)'+ N9 W( ]; \3 C+ N2 e# X/ `7 Z
Enabled = False2 N8 m+ o' t8 T7 w2 ~5 s4 j3 Y
TabOrder = 4
' o! e) Q* d0 R1 H+ u OnClick = btnForwardClick" j" ^$ u5 E5 l
end
/ w8 C: n! I$ W$ [# |; z object btnRewind: TButton2 n9 I4 R9 b p l4 @, u
Left = 376
" B9 ?, L' o) x/ g. t7 X! f Top = 152
# {5 y" N7 a6 D Width = 754 M5 V% k" i C" @ U) s+ K1 S
Height = 25) ~2 @/ J8 S/ w
Caption = ‘ 上 一 句( &W)'# T9 a& U! K7 P3 u3 p' V, _9 ?
Enabled = False
" _3 Y+ h) D6 d, M0 y TabOrder = 5; @1 u1 X6 r1 @* z3 X6 W* b
OnClick = btnRewindClick
) }! O5 R9 a7 h5 a4 c" ~3 ?) { end
) ~0 J) J0 c! `* t7 d H' Q end
# \% {) Z1 f. G/ t f----关 键 代 码 段 如 下:
4 l' j3 x! Z4 O# g) L: O---- 1. 朗 读 与 停 止
2 J" n& {1 b- c- \ ...1 [* d3 T' j8 y0 n/ h8 N; J1 w
procedure TfrmMain.btnReadClick(Sender: TObject);
# {: X W+ |- b, J begin& c0 o* x$ _# k7 Q3 l
FISpeech.Speak(memText.Lines.Text, vtxtst_
7 e3 J, X4 u- {) z7 f7 cREADING);
0 ~3 n* e7 D6 o( w- _ btnPause.Enabled := True;, F6 E4 {7 U: I2 Y
btnStop.Enabled := True;
. R! f) R( e h6 J/ h" @( Y end;
2 w7 a5 L$ l# c, g* n: W' k
7 I0 p0 n( `* m% m! _procedure TfrmMain.btnStopClick(Sender: TObject);0 O1 ]6 q. ^: b
begin
1 a7 i. q. {( T: v FISpeech.StopSpeaking;6 \- N" O r! p$ \
btnPause.Enabled := False;5 D: J6 d6 f Q3 a4 ]
btnStop.Enabled := False;
) O" ^, l1 l$ E7 C0 A9 g( \ btnPause.Caption := ‘ 暂 停( &P)';
$ m) x+ _: F3 r- E$ q end;
! S( ^7 ?4 N: C ...
7 L. @7 E7 N- R----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 9 A' j8 b- R3 a/ S; ]; \
: o7 t% @% R, h' a1 r/ B7 g---- 2. 暂 停 与 恢 复 ; `$ A |- B8 a* c8 ^
...! L* S H5 v$ e( ?8 I, d4 j
procedure TfrmMain.btnPauseClick(Sender: TObject);5 o5 w8 C; I. A2 _/ l* H
begin8 |: d( K: y' C( ^
with FISpeech do
5 M. q5 y |" t& a' T+ w# x7 l( N if IsSpeaking then- {' H; \* s7 i% G/ t( T- Q8 ?
begin
' A. L# e- v, i, s# `7 ~% T I AudioPause;! c. x& f% P0 p* X5 n$ u1 V5 P$ I
btnPause.Caption := ‘ 恢 复( &R)';
/ U( B2 _6 O3 u; |4 p- ` end1 C5 c) t( w: d
else" D# \4 z- k% k8 L
begin- w# `; @ k% m* W% N
AudioResume;
_. l1 c% B" I btnPause.Caption := ‘ 暂 停( &P)';
" @9 h& c: ?6 Y end;6 K9 ?$ Q, n0 Z% y; \
end;
7 | {) {& y$ h# ~- Y...
* F5 {8 h e# C: @----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
7 U& D0 C! D6 c- w" `. |----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 % n% K7 Z( S" ^! K$ N- Z
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: . P( x8 p t! U
...
, i& }+ I, R2 h+ P( \IVTxtAuto = interface(IDispatch)
- d8 g+ Y4 \& d8 t% y2 R, @ ...
' Z) P3 S. f+ V- L5 R2 ?7 U- J( a* ]0 O: B property Speed: Integer read Get_Speed write Set_Speed;
& y, a% I# N' F8 F' ] property Enabled: Integer read Get_Enabled write Set_Enabled;. m- m# j2 A: X& @
.... P- z+ c% Z1 ~# B9 @8 T- n6 o
end;
7 J+ @# D+ F0 Y6 b# p9 o- I ...
[0 y# r* M/ n y----即 可 正 常 使 用Speed 和Enabled 属 性 了。
l9 J* Y8 N, W l- N, t5 X* O----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 ( v$ E6 ]! _! x0 @) M
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。. T) K$ ?. }# d) k% K$ u/ [4 U8 z
/ q$ C7 P& P9 L# x9 n) b, N |