|
) I1 P9 t* [: G" C
华 中 师 范 大 学 卢 小 海(flier@126.com)
/ R( ?) x/ y& F8 D 各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
`$ o2 l- i7 B3 ^" `
* n' h9 d6 J Z5 M! K: Q ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
, w+ `& |7 ]( Z% i ^3 A5 r4 Q----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
( d6 w8 t& M6 W, O) N2 w6 C" s: m----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
! n g& g" \. S8 z8 Z& ^! D----再 在Delphi 里 新 建 一 个Application。
1 E3 `6 j' Z- u----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
6 c0 E" j0 x3 m5 ^4 y----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
- y8 H# g1 T: M1 _: O----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
( T0 B3 e* i0 g* p) u ...
( d; r& V( T" l8 I7 p$ c procedure TfrmMain.FormCreate(Sender: TObject);& K4 e* l& E- d; o& U
begin
9 e& ?- G/ K& d, w$ H( u" W FISpeech := CoVTxtAuto_.Create;6 S2 M4 v" \8 V" \: A0 X! n; U
FISpeech.Register(‘Demo Site', ‘Demo App'); _4 r+ ~) M% j7 y
end;. U' y! ^4 ]9 ^( F: J3 M' D) {+ b
...
, b! q- t: ?: C& S----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 8 @# ~9 P$ z1 z' s s+ G; J' y
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 3 t+ r2 M$ `5 O, y! `
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 8 L1 f" S4 k% ?4 o
Form 定 义 如 下: , D9 r( k# U& A* K q; {/ }+ R2 n
object frmMain: TfrmMain3 t5 ~' [( T7 w7 W8 ?
Left = 296- C6 Q- ]1 Q/ }/ E( }. J- |+ }; P
Top = 187
2 I' k; a3 R- G8 _% \1 s# R, L BorderStyle = bsDialog
" m: b7 n2 ^$ Q8 L4 \! N* P Caption = ‘ 英 文 全 文 朗 读 演 示'4 @ O4 `4 o0 N& o4 w
ClientHeight = 185
) Z& }. f! z1 t! W ClientWidth = 456
: [. M W2 i1 y5 x/ @ Color = clBtnFace3 t9 _% r, g* F1 \; s" }$ t; Y' i
Font.Charset = GB2312_CHARSET4 l* H3 @/ x, r7 j0 N9 n
Font.Color = clWindowText
% ?/ \/ k* r |3 u2 W- ?+ R/ ~5 r Font.Height = -12: l6 a5 I4 [0 {- k
Font.Name = ‘ 宋 体'
/ L: E) j( T! [0 Q( y# r$ f5 b Font.Style = []
- Z* x) v# s: \* ^ p! L! }! ]9 A OldCreateOrder = False
, O9 p4 |, {" o3 Q" c: N! o2 i Position = poDesktopCenter
. v/ D) n1 ]& g* @" B: |4 {* Z1 y1 t2 w OnCreate = FormCreate" y& N2 K/ a" X6 W0 j- _* f) G
PixelsPerInch = 96
' Z( o2 Y( Q. K4 Y- j u TextHeight = 12
$ o3 T& k( |5 ^& y4 c' X object memText: TMemo
& G1 U( n2 Y5 a; }, k. ? Left = 87 N7 }" F4 _/ T5 Q6 R
Top = 8. h6 O3 m! V3 g# h
Width = 361$ ?/ j3 Y6 g- t+ l8 S
Height = 169
0 q; v' S5 Y4 E7 T! f' c ScrollBars = ssVertical
. n* o* e1 |/ A p9 A) S& D5 H TabOrder = 0
! [+ }& M Q/ n! ~4 u end6 G- u, |& i9 z( W9 R8 N, H) B# U7 O: v
object btnRead: TButton
# O9 {- [5 j2 V* y5 N& P Left = 376
# m/ {9 p3 A. z$ A- v% y2 ` Top = 8
/ T( z8 l( p8 _8 q& d+ F1 G Width = 75
; j* u4 b" {+ p6 |7 T! \ Height = 25
' }. q/ ^; P( i2 U Caption = ‘ 朗 读( &R)'7 _. n& M8 n: d0 G
TabOrder = 1
% ~% W+ w. Z" D OnClick = btnReadClick2 E, }+ U6 B0 o6 f R+ o* E6 C0 u
end8 q) v. G! d9 T
object btnPause: TButton* I q; s3 c+ U8 w2 z
Left = 376; S! B( J$ A6 N+ ~* S- O$ q: |. {
Top = 40
+ r7 t. F! S2 H3 s5 o) H8 a Width = 75
+ B- Y! f7 t$ y8 ?- l& a: ]/ O7 g- K Height = 25
& y4 |) o' V8 b# |7 t5 \7 Z0 R9 x Caption = ‘ 暂 停( &P)'5 v) J O' p+ c/ h' ^( h5 J- h% X2 K; n
Enabled = False
, G" j0 G+ w+ Z TabOrder = 2
( \/ T# r/ z7 N% i, ? OnClick = btnPauseClick5 T! ]& h2 [" U, ?7 M% A
end
& K) q7 f+ ~# A! w: W, ^+ C object btnStop: TButton
4 |( T7 p' b+ o" Q! h# x Left = 376
6 j; `& }6 U& Y" `3 W2 X Top = 72% L0 G2 R* r: y* u( `
Width = 75' ~$ ?0 W; T- k
Height = 251 n. B8 ~/ r( I0 d5 G$ m$ D
Caption = ‘ 停 止( &S)'
$ t8 ]8 Q {1 s% H; S6 z Enabled = False5 J& Q; Z( K1 Y, ~: ^
TabOrder = 3
' [9 T/ w; B7 E OnClick = btnStopClick1 P2 t$ n! v$ a, m- B0 k: j
end9 b% ^& a6 g: [9 h1 n0 d6 Y
object btnForward: TButton5 q; R/ X, E! p4 B& T" i3 m
Left = 376
' }/ y" R1 u: d' \ Top = 120
; ~( n$ F3 h' F5 p; \& k Width = 75
0 e- S/ D2 ^. r- p Height = 25
& F3 F; U7 v9 Q$ T) ?& u: q Caption = ‘ 下 一 句( &N)'& C/ q: |0 d: G: ]
Enabled = False
$ j { ^& ]0 @) ^ TabOrder = 49 b0 q: [& O) r3 Z
OnClick = btnForwardClick
& k! [$ i- Y# ? end
7 q( ^& S$ K+ Q. B& A1 w! e object btnRewind: TButton- E2 q1 s B6 V r% M% C8 [. z
Left = 3761 k$ v+ n( W2 B% s3 P& Y& }& r4 l
Top = 1522 R8 T" S5 _* V$ N' F
Width = 75
- B" {! V% m: J' d# j+ ` Height = 25
# V ~4 X8 e/ b8 u1 u0 _9 ~ Caption = ‘ 上 一 句( &W)'/ d: u( r: w* p1 O5 v* C$ n
Enabled = False$ ^* T% n1 s+ b7 a, L/ W+ O
TabOrder = 53 |$ q2 [7 F( a" g3 `' i( G( Z
OnClick = btnRewindClick
2 N* {5 R( M, b$ R" D end( ^: n* _& @) i. m- {4 a
end
) z8 I9 h) A1 r$ Y6 h. Y----关 键 代 码 段 如 下:
- s$ [/ S& }# X# q---- 1. 朗 读 与 停 止
% s5 q; ]) N: G6 X. L3 T ...0 J# b* B5 T, f/ f, Z8 ]
procedure TfrmMain.btnReadClick(Sender: TObject);: B& t9 r- F0 y6 G7 ~) B2 |# F
begin: U* C5 N6 z! I, x6 X# |, x- j
FISpeech.Speak(memText.Lines.Text, vtxtst_ & z- n4 d; x/ E- e
READING);$ d. m6 ^ H, G6 {0 o
btnPause.Enabled := True;
R7 \2 @! R6 E! ^$ R* f1 d& t btnStop.Enabled := True;/ l6 |9 [6 T+ O4 a
end;
% B% h* ]8 f9 r `5 W; }9 g1 D % J! d3 Q& O; b
procedure TfrmMain.btnStopClick(Sender: TObject);* R0 p) h$ _$ i' z: j
begin3 w2 l0 E# n/ T5 m4 F4 T
FISpeech.StopSpeaking;
' ?4 P. J1 K, t1 S! j, d9 c btnPause.Enabled := False;
- P/ M6 V( h0 L3 U btnStop.Enabled := False;' _8 _3 m# w* ]
btnPause.Caption := ‘ 暂 停( &P)';
& @/ W/ {2 p9 W' g6 T" `5 u end;
3 L# Y/ X, p1 }9 C4 G ...
; I A# i' _/ R3 V- I----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
0 y( V8 _: |- C/ X# p. N- @+ g
! J# f" A0 S3 C4 A---- 2. 暂 停 与 恢 复
9 D# s+ o- D7 G) V9 j' Z- w ...2 S# I- C; a. C0 f
procedure TfrmMain.btnPauseClick(Sender: TObject);+ H; H0 w. G& i. y
begin
- u/ O1 _' p6 r+ q0 ^7 H& x with FISpeech do$ K8 c6 t# w: [; |- W8 L' | o
if IsSpeaking then
. O9 ?6 f q6 }3 T3 N" e. V) b begin& @: N/ }3 } b) X
AudioPause;
7 p" H$ N( T) \% t8 x9 R btnPause.Caption := ‘ 恢 复( &R)';
7 [! Q" J7 D( V# H a+ [4 W end
6 S' u! b) d" A5 v: S+ I else& ]! G3 ?( x# D1 u3 T' s# F5 Y F
begin# L: t6 k+ {* H2 B. f' g
AudioResume;
) a7 z2 T* S3 Y) U$ W0 j btnPause.Caption := ‘ 暂 停( &P)';
8 I$ F' M$ }0 Q/ a end;
4 A0 P7 J/ F6 r1 o( v) x9 q# Oend;
, x6 S9 n3 d4 \( }! q...
8 z. d% v, F% j+ {- A0 n: J----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 * P9 ~; \. Z3 D \5 S- a6 [# {
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
/ L0 V ^6 D7 s: a! ]$ Q, C, u----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: - D( _. j2 k# W* D( |/ a& e
...
. B* r. M" ]0 n3 \# N( xIVTxtAuto = interface(IDispatch)9 m) u8 e; l5 S3 q% }( l
...
6 u- }% W# ~. _, | property Speed: Integer read Get_Speed write Set_Speed;
- a B# E! h9 a" s M property Enabled: Integer read Get_Enabled write Set_Enabled;
/ n2 O) ~7 l8 P ...
" A B2 }1 g4 ^7 j1 hend;7 j0 C' A2 B, D) ]/ d2 c# }
... & K6 F/ }! ?1 B7 c
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 - Z% Q7 [& x9 v- n8 |0 w _( I$ L
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 9 U z: w3 W9 @0 {* R9 c. p' `
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
! E, I0 x" B7 Q
3 f% Q7 ?7 k2 j1 \6 u |