|
: u$ w, i2 D. d1 ~% L华 中 师 范 大 学 卢 小 海(flier@126.com) 1 k$ S L1 y2 r) P; M% M
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
( Q9 q7 g4 S. m/ ?. w4 c2 X4 Q" p6 K, L( j+ r6 {* C
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
: [1 i$ Z, T d. C: x7 ?----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 $ K9 s& X" W) |$ P0 [7 k) ?3 P2 J
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 * r) j b4 @( K7 @+ d7 v/ J
----再 在Delphi 里 新 建 一 个Application。 5 ?; a3 k: l+ G
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 7 U$ A8 W, c+ K% \( K/ D, M
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 ' \' p0 C8 H, S5 X/ r3 J
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
' X; }! C& R I, i( N7 B ...
6 N* \. E# E! C/ `* | procedure TfrmMain.FormCreate(Sender: TObject);
2 Q, `6 u+ i+ C, d begin
% o$ \$ B6 {) X4 N) A" R FISpeech := CoVTxtAuto_.Create;
( a5 s8 Y. ]! Q0 O$ e; |' ^0 ] FISpeech.Register(‘Demo Site', ‘Demo App');
; S" f$ @8 {3 T. ?$ ~4 r; r8 v8 H end;
& Y# b5 |) a$ r2 o1 {( r... 4 p- [% @2 n0 v- P- q# g9 d
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 $ X) b, `, x3 A- W/ ~! P2 G
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 6 P# s+ {& N' \$ f7 X) i
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 ( y) Y0 `4 N `6 }7 }4 O6 q
Form 定 义 如 下:
- M8 h) e# o) C% u object frmMain: TfrmMain% z S' X& m; x9 V/ {
Left = 296
n9 U3 p1 C9 f3 m4 i& Z7 G4 } Top = 187
9 W8 {$ {8 D' c" a" _+ f$ Q3 Q BorderStyle = bsDialog' u6 H. ~4 x' ^# Z4 [+ ?
Caption = ‘ 英 文 全 文 朗 读 演 示'0 k# n' [5 {/ e
ClientHeight = 185& M0 _' ?- S# X, {/ b
ClientWidth = 4563 e( t) v4 A2 e# B; t
Color = clBtnFace
0 u3 o4 _2 \+ Z Font.Charset = GB2312_CHARSET5 I6 e3 q" _7 ?# E; e/ g% i
Font.Color = clWindowText: z6 Z- r J1 q" f
Font.Height = -12
( }5 z L, J) O2 d6 U! T Font.Name = ‘ 宋 体'
! c$ Z$ F: G2 U; D Font.Style = []" u8 Q3 r L, N% U2 b
OldCreateOrder = False
6 X d4 f# J" ^5 @; i Position = poDesktopCenter- z. E( g. ~, v3 y" p* ?2 A" Q% M/ L
OnCreate = FormCreate% }' F: K/ k w
PixelsPerInch = 96, O& e! x X. u- Y
TextHeight = 12
4 v4 M3 X7 h! Y, G; Z$ f. n x% u2 { object memText: TMemo
: P& t% W; J$ a: k# Z# ] Left = 8' t8 {& E# G: t
Top = 87 `5 [/ m/ \$ s4 P3 X
Width = 361
9 w% t9 y' d; M4 j Height = 1693 D& }2 j2 [& x* l
ScrollBars = ssVertical
" F8 j0 H, i3 H3 D# i TabOrder = 01 D4 q0 f0 Z, j+ X; f" D* d+ h) `
end- B' w# E% s, r8 O8 Y+ x8 z
object btnRead: TButton
% }7 `5 G' i# j Left = 376, C# y- r. C( T3 _8 b F* \- a
Top = 8 L, X7 m' ^1 e5 o* w: k
Width = 75
# O) [* }5 d5 G9 R7 u7 }' m4 s7 n3 E Height = 25
; C, s& A5 ^3 c M: A, k/ v Caption = ‘ 朗 读( &R)'
: `6 \! D1 S. T0 w3 P5 j6 O7 z* s5 S TabOrder = 14 ^1 H8 ?" [" s x& _
OnClick = btnReadClick* N- w; p8 M4 n2 Z4 M
end( Q* g; |4 }1 ~7 O% T; v, a
object btnPause: TButton
. u) ?7 C! W+ Z* b8 | Left = 376, f3 o$ {: u, t% \/ O
Top = 40- G y/ c4 v9 L- D6 |5 y' w* f5 S
Width = 75
" B8 H& u& `2 f1 z* b+ j Height = 25
" I1 K- G8 u% k Caption = ‘ 暂 停( &P)'
$ d5 |; V0 Y" c0 q+ c Enabled = False
' \9 r/ m M) S. q6 S9 h( l TabOrder = 2% @$ ^# c! F& D5 P9 t0 F
OnClick = btnPauseClick
# K6 w* Y# ^7 X9 V& J; O end
& n9 o$ |6 [, A7 A- U2 G object btnStop: TButton
8 o+ k3 B6 T% l! s, a& I6 W Left = 376. d( U \) {9 }- e0 f
Top = 72# _/ k6 r- V7 }$ ~6 b- k0 G
Width = 75; K* |5 M3 m& Z k+ X
Height = 25$ h! [' F B9 }' E7 N; t$ G
Caption = ‘ 停 止( &S)'
* y3 e7 K; O2 z. B" t! x# B& C Enabled = False
* {) S: M3 ^3 s5 z E# [" i, k4 ` TabOrder = 3
+ L0 m! u; Z. x0 _% E3 e0 a4 T2 F OnClick = btnStopClick( S( Y: W( G( ?% E) A
end
6 S! r) a& @7 T, K- Y+ Z! a. J, G. u1 F5 @ object btnForward: TButton1 J3 ~3 [4 e2 Z- {& z
Left = 3761 n2 J7 W( u, q; b' k0 L, S- |+ }- w
Top = 120
; d" ^3 a' D2 ?7 Q Width = 75
! v3 u) K, |9 g0 N3 z+ p& N2 ^, t Height = 25
) l; L& B8 g! M/ o, h) n' d+ ]" B/ }$ @! g Caption = ‘ 下 一 句( &N)'1 M' K1 l$ S4 X# n: N v9 J
Enabled = False
3 n* J; }. q9 V7 c. K0 E# ^2 \ TabOrder = 4' U/ }: R9 P& i. g8 z- n
OnClick = btnForwardClick
0 B* R( y+ n( M' s& D end
1 g( i7 ]2 f1 R( `2 b8 j( r% w* Q* M& X object btnRewind: TButton2 C, Q" e6 H: J, L! J
Left = 376" K) l1 V @ y: j& u- G5 y
Top = 152
. n/ j' U9 p% X& U9 u Width = 75
1 J$ d* O6 e+ o Height = 254 w5 r5 \2 f( y0 l
Caption = ‘ 上 一 句( &W)'& D j- O; o8 Q3 I) R5 [( ]
Enabled = False
2 p2 Q) o% {' F. Y: C& U% N TabOrder = 5
$ D5 \' o. A# f! F OnClick = btnRewindClick
: A6 K6 M* `2 H: a! X end0 l T( }3 x" n6 M$ B+ |& A
end 4 |; q8 }; s6 R. Y; i' q
----关 键 代 码 段 如 下: ! E& ]7 w- I% L$ A y. s- o
---- 1. 朗 读 与 停 止 9 u0 g5 a) P+ x9 f/ j
...) k. q* J. `' s
procedure TfrmMain.btnReadClick(Sender: TObject);
7 `- \0 t" t) K- t, _2 [6 {3 `9 @ begin
1 h( k, V: f; z- S) V FISpeech.Speak(memText.Lines.Text, vtxtst_ 9 F8 K7 k$ ~* i7 K
READING);
% p: R- R, V r) K4 B btnPause.Enabled := True;
4 A) x* n8 ~$ C! I9 w, q/ ?% i btnStop.Enabled := True;& @, ?3 K: v% l8 o8 o- w6 E, c8 [
end;9 s6 t" A( D/ G4 x0 d! N% Q
' B1 E7 |1 Z6 W# ^5 T# Vprocedure TfrmMain.btnStopClick(Sender: TObject);6 X* e1 [! L( }" u5 W: l
begin2 ]+ [1 i6 g/ T. v3 R2 i
FISpeech.StopSpeaking;
3 _" {' x0 i$ e( c# h' r1 n btnPause.Enabled := False;
6 N( O! `$ \9 I; t8 K7 F btnStop.Enabled := False; w; [6 I) j& \9 n4 z$ D5 U* R; v
btnPause.Caption := ‘ 暂 停( &P)'; U& M' Z1 e% V1 j9 U2 E
end;8 t6 y9 L9 ~5 v+ }, x/ n* F; G, e
... 6 `# k W$ X1 T
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
: C8 V% p: B" P! l9 l9 j* A+ J1 c3 b7 U* n
---- 2. 暂 停 与 恢 复
7 J( y2 x$ }/ p" \6 Y8 v ...; ^' V! J4 n) n" y" A
procedure TfrmMain.btnPauseClick(Sender: TObject);
; Q7 j, p* g* y( c) s2 x9 M begin8 R/ \' ]6 y4 m
with FISpeech do. I0 U4 Z( l' B$ w _: U
if IsSpeaking then
7 L. w) r1 p' W; H3 S+ d6 C. [ begin* b8 H" m0 k- G1 }! f3 W6 M
AudioPause;
, B n3 h& k8 b! r5 C5 Q btnPause.Caption := ‘ 恢 复( &R)';, p- ~/ f8 i% C* W' R
end
' `3 x1 m7 z! N% c1 }) v2 g0 N else
% D% g- J! o5 i) b* U begin o% ~# w: Q; M' [9 Y: y6 C( \
AudioResume;
; j" u. L! G4 J* w8 a2 l* `2 q btnPause.Caption := ‘ 暂 停( &P)';. X9 X( V4 E) B* s
end;5 |& j" D' U. ?. d l, d* x
end;7 O: y, r& s I( S: k
...
7 c9 M& E4 ^* K' B4 \----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
0 l6 s6 g: x* q# t: U2 }----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 7 G7 g0 ^" q/ U
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: , |' F! k! ~7 w$ _
...
9 C" s5 X" c( ]! D9 |* c; NIVTxtAuto = interface(IDispatch)
9 L9 |7 ~) j8 w* i$ \7 z4 z4 Q ...! Q, X, N. T+ z; c' j! N
property Speed: Integer read Get_Speed write Set_Speed;
V5 Q$ l7 Q3 w# c p6 y* Q7 O) J property Enabled: Integer read Get_Enabled write Set_Enabled;3 B5 f; L6 j8 p; |2 L
...: y1 T0 X# p1 N2 H9 H
end;
' C3 F& O3 n" I! [4 B% p( I4 ~1 N5 \ ...
7 k$ m8 ~, A" A% c! z" f----即 可 正 常 使 用Speed 和Enabled 属 性 了。 ; P" ^: @0 n) Q5 c9 X, S
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 : u9 h7 w0 {# x1 f5 B- [
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
9 C/ v5 P) ^+ d6 Z# l2 O ; v" p6 ~& r5 f# U4 Z
|