|
' L( j# ]; f/ ]( K6 v& b华 中 师 范 大 学 卢 小 海(flier@126.com) ) R& H4 N" m& H! k
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
! f% y j) K. s9 R
6 a, D! Z' K; } ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 9 ~% Y& W8 I9 R: S
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。 ; v) \4 e: d, V$ }! A
----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。
% E. u- r2 V1 ~; d" |) W& q----再 在Delphi 里 新 建 一 个Application。
' R; s# M6 N( q----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
3 I# R& A, w+ \! X' [2 c----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 & V; \3 T a9 r7 r; _0 R' N
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
% Y) w2 k ~+ x0 ^( v8 X4 ]& k% G .... N; Z5 T& ^9 i% [
procedure TfrmMain.FormCreate(Sender: TObject);3 \0 I( M+ z# N; A* z. v' D1 I
begin) L( U1 ?8 J- p% Z- o. ^3 @
FISpeech := CoVTxtAuto_.Create;/ K: E6 V+ e3 h6 d2 e$ K1 s* b
FISpeech.Register(‘Demo Site', ‘Demo App');' P; V7 W8 R; F4 d p1 X
end;
0 J2 a$ g% a* i& q... " i3 ^; {( W7 Q" f/ X
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 0 Y6 G, [! a: a" u$ n8 ~
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 7 X& t; E5 W& J% {
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 3 h: `8 A+ t! `: k/ T6 w3 s1 i2 D2 v
Form 定 义 如 下: " z% D2 N- Q; s( R9 G
object frmMain: TfrmMain
; R9 e' w/ H9 [! b# J- A Left = 2964 n; N% z a( M4 V. ?" [
Top = 187
- a" q7 d2 y$ y6 h9 r1 ` BorderStyle = bsDialog
8 Q! _( b' b: c. i$ H0 p; ]2 f0 b6 \ Caption = ‘ 英 文 全 文 朗 读 演 示'
3 }5 Z* b: ]5 B, U# _ ClientHeight = 185
# S; [0 ?9 p3 p+ m, D7 P4 o ClientWidth = 456
8 G4 \1 |" G* {" P) {2 e5 w- i Color = clBtnFace
7 m8 g1 s/ e0 h6 V* F* A Font.Charset = GB2312_CHARSET8 G0 i. ^% R; Q# b8 _
Font.Color = clWindowText& _: c, d* {/ S. {; o+ n+ n
Font.Height = -12
! T4 O4 i9 _- h7 h8 v Font.Name = ‘ 宋 体'0 U, L: J, u! F! w1 L
Font.Style = []
# ]* H$ I* v" M5 q# \% u0 G OldCreateOrder = False0 h, j U6 N7 s2 _* @
Position = poDesktopCenter
( s* `: l* E9 v+ Z9 _* V OnCreate = FormCreate
% q( t% `! X: C) D# e; V PixelsPerInch = 969 g7 u i7 ^' M( A5 h6 C: _
TextHeight = 12. E/ p9 m5 h6 \0 f6 v- I1 v
object memText: TMemo; j$ v* i7 ^& Q+ Q# P0 [* r5 {
Left = 8
4 F, \/ j* I. v* Y% r Top = 8
0 ~" h9 E& I; E Width = 361# p! e, Z& Y6 v. E/ A* m6 |
Height = 169 e* K1 r4 }/ T* Y2 B
ScrollBars = ssVertical
% k1 s( X, @+ ?; w+ r. y3 o TabOrder = 0
# \2 c1 H, W( q, m+ t6 M end! u/ v" m" n, b
object btnRead: TButton
8 s4 e V( \. Q8 g/ t Left = 376, M2 I: J) X0 R
Top = 8, f6 _& @, t/ i& C$ f3 O
Width = 75
# j- x7 \4 F/ r$ c Height = 25$ d% R5 \% N# a
Caption = ‘ 朗 读( &R)'
2 M" A; u5 R% S TabOrder = 1! f* F$ m9 I1 x+ C* E% X7 P
OnClick = btnReadClick
# u" s) M5 o. q% J. g: P end( P- }' i) }- Y8 Q4 o
object btnPause: TButton
3 f, Q) n, S P Left = 376
% ?8 r0 J6 p4 G' Y! s$ H* I0 f' Y Top = 40
, q8 Z$ h5 w0 m, _" E9 Z Width = 75' C5 y9 a' o1 `% S: w5 q
Height = 25 K+ j% G' `& }: }* R: ?, G7 w
Caption = ‘ 暂 停( &P)'4 L6 E6 w0 D F, w' U3 A0 q
Enabled = False y r3 t: x2 Q6 s( z4 |; U- N
TabOrder = 2
) I9 Y$ d% Y- Z/ l" n8 P OnClick = btnPauseClick
7 \' Z6 _% \5 h4 \& L% p end8 a3 i) D! j0 t; t8 p: {! g, B. H
object btnStop: TButton
$ b4 z0 p5 J/ }* W; V Left = 376
N& w$ x. C4 p, o$ ^ Top = 72
$ ~* G- H+ x ^/ ]+ [. }. i* m/ V Width = 75
+ O6 J9 x/ J5 Q# G Height = 25
* E. u* h; j, L! C& @% q; c. ]+ E' I Caption = ‘ 停 止( &S)'; l5 |4 W. E( l" ^3 y
Enabled = False% J4 A& Y9 h9 v
TabOrder = 3
5 ^$ |$ e- `1 b0 P$ W3 o OnClick = btnStopClick$ V4 l& i2 q) F! y* T6 G- R2 a: ]
end( m$ R9 u; I; j
object btnForward: TButton
& u) \, N, I( X; N; @ Left = 3765 |" F! Z0 n5 I2 |, N. U& l; \) q# ?
Top = 120
$ k1 N w% k; s2 E2 L2 [ Width = 753 O. F }1 Z1 Q# ?7 J$ A
Height = 25
, k# @# q* `0 C# T4 _* D$ c4 s Caption = ‘ 下 一 句( &N)'1 @* m: }5 N1 I' |$ f
Enabled = False
8 Z4 {: \# O! u1 B P' \6 _ TabOrder = 41 k5 ^( x; o7 a/ d, r
OnClick = btnForwardClick
2 `. S5 t# b* S! O- ~3 y/ V end
! {! I% Y- Y/ Z4 E. @ object btnRewind: TButton
9 W- X+ `) Z1 ^) d! Q) Z Left = 3761 P( B5 h* k: I; d
Top = 152
" d1 s2 \" l. b3 u1 q7 q Width = 754 w0 Z, O$ \8 _/ r2 n
Height = 25+ Y6 W+ `6 ^0 w+ h T' W' {' |
Caption = ‘ 上 一 句( &W)'
+ o$ C6 |, i: y' u7 G: v Enabled = False
& m6 Z5 A" h" n! C7 R+ M) q, S$ I TabOrder = 5
3 f5 d7 m! |( N8 X( a# X/ w( A OnClick = btnRewindClick" T' ^, k1 }, K
end
3 L. d. E$ j0 }" _5 W: `9 e end
9 w0 F8 ~+ ~! A6 b& s% }0 j* w----关 键 代 码 段 如 下: " y6 U& J% p8 H/ G
---- 1. 朗 读 与 停 止
D8 D+ [2 b; e2 f" n6 |2 Y0 M ...7 A1 }% `1 ]/ e8 j/ O
procedure TfrmMain.btnReadClick(Sender: TObject);
) C; g+ _2 z: S6 | begin
. B2 \6 o% L; |6 c& a% O FISpeech.Speak(memText.Lines.Text, vtxtst_
3 q2 T/ ]; P" g. TREADING);% ~* i$ _% C( ^0 L- p9 t( a- {
btnPause.Enabled := True;- T2 W8 E; O5 q2 u! r
btnStop.Enabled := True;- n. Z! V/ j4 v: V. [) O
end;
0 S+ i: M8 G6 X. A3 ]: c; R9 n
+ G3 l! ?. E5 ]( |6 f. cprocedure TfrmMain.btnStopClick(Sender: TObject);8 R. P$ D9 L% r; E# r: c- N
begin
# C/ s3 Y* }1 _# I: c! }% ^ FISpeech.StopSpeaking;. F; V1 S Q1 Y# F
btnPause.Enabled := False;' @' c% Z, E4 U
btnStop.Enabled := False;
# @6 z2 {; [2 [& y# L W) G btnPause.Caption := ‘ 暂 停( &P)';8 `- `4 V6 d, C' z
end;
; }* u* u" J4 k' u$ ?) H% @ ...
# r% _% g; w" Y3 {----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 8 e+ L) p/ Z5 \% z' k4 S$ @# {
% ~! V& V; ~( ?( l3 O6 s---- 2. 暂 停 与 恢 复
5 i/ q/ g6 M+ W* Y) s* E$ }: f# p. L ..., j+ q2 c% m8 V" M; i
procedure TfrmMain.btnPauseClick(Sender: TObject);9 \3 k1 r- J0 b1 b8 }6 R
begin
- Z% a1 U: \" W l! D% h3 ~ with FISpeech do% t# j t6 @/ L+ I2 L, @
if IsSpeaking then! {" k* V. }; P
begin
6 z R' |8 u* c+ L. R/ i" N3 z9 f* @ AudioPause;# M+ c8 c( b& w/ ?
btnPause.Caption := ‘ 恢 复( &R)';
' X- d: F ^+ ~) z# ]" n end/ [; d9 y: h- t0 B' o" q
else {( \' T6 P! ]
begin
$ G/ K8 B f3 N! o K; V0 n9 f AudioResume;
$ N7 r2 `8 _7 r; P! z. J/ f btnPause.Caption := ‘ 暂 停( &P)';6 y. o/ y( v4 ?1 z D$ a
end;( H# `4 l0 T( X- ]8 l! m/ I
end;
$ [; S& ~2 v7 a. i f' Q...
8 L' ]0 q( q# [----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 * ]( p6 ^8 ^* x6 J$ w
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。
- R& Z- t+ |- ]! E& Z" `: h----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: + j) \2 z1 {& P3 B
...3 S1 A: N/ z, x# V2 s
IVTxtAuto = interface(IDispatch)2 p1 Y/ `" v* U; ~, l
... ~4 ^! a. @- ?) \
property Speed: Integer read Get_Speed write Set_Speed;- W" L2 q$ F7 v! c) E4 P) |/ p* i
property Enabled: Integer read Get_Enabled write Set_Enabled;# k4 r, Y4 v! d' c3 W: D4 ]. w
...
, x7 O" G4 P6 V: B/ X: |6 d. Eend;' ~. j) f+ _4 x& T
...
1 C& t" g; M: x' N4 d, H----即 可 正 常 使 用Speed 和Enabled 属 性 了。
; r0 ^% t3 g s# }% T4 h2 n----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
' z, {% L" S2 k2 ~- v2 E----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。) d- z9 k) [( z- ?+ m. m, w
1 T S/ _7 f9 o9 Q- ] |