|
0 L8 x$ H/ c7 k/ F2 `华 中 师 范 大 学 卢 小 海(flier@126.com) - d' z- R* ~% f) S H
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
% u S/ k1 o0 N0 J; X6 k1 N3 N9 n. X; c' ~# H% ~
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 # V9 Z+ W# E) ?9 |6 E; b9 X+ I
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
R1 g* y' \; v9 E3 D' N----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 $ q# ?6 S+ P: s- h1 c0 F
----再 在Delphi 里 新 建 一 个Application。
: _6 ]& j! g6 ^+ i5 B----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。
% g, K8 {6 n5 k/ T9 I----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
0 @3 F8 M7 t# ^& U----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
* ~3 y7 O- |' }6 G, s9 K ...
, P" b# n" T h4 f* E5 y) ~ procedure TfrmMain.FormCreate(Sender: TObject);
5 W, a5 d0 F* V( m9 n6 @ begin: C) d2 s+ P8 t& O
FISpeech := CoVTxtAuto_.Create;* j! |7 e9 N; f- v
FISpeech.Register(‘Demo Site', ‘Demo App');' t" X! U. Y! f. p
end;9 W* G$ {& M7 e8 L, X! v$ B+ O
... $ @% Y8 k% }5 a" H
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 4 a1 x! U/ \; t2 Y
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。
7 H7 K4 a* Q( N, K----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 ; P @; d3 c5 S, H4 S8 P
Form 定 义 如 下:
! ]: z" {. y. q& q object frmMain: TfrmMain, d4 M' u1 m( o8 E6 l! Y
Left = 296 _) H$ R; X# f6 ]! I, ^
Top = 1876 c6 ]& b, a: d6 \$ L+ K
BorderStyle = bsDialog6 C ]1 _7 Z% I; y
Caption = ‘ 英 文 全 文 朗 读 演 示'
8 `+ v# n& H v0 w5 w& @ ClientHeight = 185/ U: a- V, G i
ClientWidth = 456
M' N3 o0 j/ o. a9 | Color = clBtnFace2 i3 n+ V! U! t1 ~4 C' a9 s
Font.Charset = GB2312_CHARSET u2 B2 k' g) C1 p4 {) E
Font.Color = clWindowText ? {/ K: J( ` r* |7 b
Font.Height = -12
6 i f+ h) s, q, u Font.Name = ‘ 宋 体'
$ K: k/ v/ }. l( ^0 V- ]4 \! ~ Font.Style = []! S' B5 t5 C$ j% A* a
OldCreateOrder = False
( o/ h: ]- L( k4 ~" a Position = poDesktopCenter3 ?* K0 E2 u- W/ a5 f4 k
OnCreate = FormCreate
$ b1 e$ L) l' ?, Z9 @) h PixelsPerInch = 96
. Q) W) I! O1 {* R' k0 c7 j. Z TextHeight = 12. G$ @0 J) }: ]
object memText: TMemo% S2 S8 [; x7 e) H$ k- [7 W6 X
Left = 8
, C: [ s, M7 P+ L Top = 80 @( l8 i ~' ~" A/ e. u
Width = 361
; `3 O: M" Y& c! u: a1 f Height = 169
" y8 {4 w6 A: n/ Z" \1 D8 E d ScrollBars = ssVertical
0 R7 b% Y2 i! Q& _2 ~: N# @$ F TabOrder = 0& s$ A7 b% @' Y. x& F9 O5 J
end7 K3 ^, r2 U+ k* {! W4 y
object btnRead: TButton
. D& d. p0 Y" j8 C7 o7 W+ ] Left = 376
0 T" G: Z7 q( }+ X( m% O4 [ Top = 81 Z& u; v& _5 Q0 k# P
Width = 75
8 N3 h3 K7 D% w9 B8 ~7 R0 p9 u Height = 25
+ w8 E5 ]& g$ L) M Caption = ‘ 朗 读( &R)'; w& ]. U. ~# G4 ^
TabOrder = 19 d) d7 r. a( V$ ^9 J1 \
OnClick = btnReadClick1 ]' A& m( j9 v2 f
end+ ]- v R1 V$ S0 c
object btnPause: TButton) ^9 G. ^* Z% {) y, \3 ^4 l
Left = 3760 o% ~3 g- F+ P" d' x+ b8 D3 h% u" i$ L
Top = 40
, F/ S- c7 T. @6 Y: T! Y) W, ? Width = 75
; z5 X5 n* V& R9 ~) u3 S Height = 25
; Q- Q7 w2 b2 [( P9 G6 [ Caption = ‘ 暂 停( &P)'
9 u: I* K2 K, t% f" v' n" h Enabled = False
/ w" `$ K5 ~0 E4 w; @3 c C2 u TabOrder = 2# ?0 J+ Z) |6 s8 W
OnClick = btnPauseClick% p: r5 M& _5 o; C# a. c% ~) `
end9 d& [/ c# Q; r% A
object btnStop: TButton9 U" `4 @1 C( G/ S/ p
Left = 376, Q- U6 `( p& r
Top = 72
( t8 D2 P' _/ a5 w( ^/ m3 P Width = 75
G$ X% l8 d8 R8 |$ G4 t Height = 258 U0 P2 N) o2 F6 _
Caption = ‘ 停 止( &S)'
9 q8 ?% d/ C5 q, j. O Enabled = False& R v/ m0 e' S4 X4 ?0 Y; \
TabOrder = 3, k9 w, Q+ ?- y! ~4 V. U d6 i
OnClick = btnStopClick" J: F' v5 ~8 ]& ?; z& Y s0 h8 `
end
+ R% x$ @) x" f% `' B object btnForward: TButton3 u, q2 J" S" C0 V. T0 W3 [
Left = 376
; Y: E7 A. h h2 c3 }1 z Top = 120
d0 d4 B2 f7 j& K6 G( w. n Width = 753 u1 U8 U3 }0 D7 P8 y/ U& h+ M
Height = 25: e1 u" X2 y- _) B! A
Caption = ‘ 下 一 句( &N)'9 Y3 k- w3 B1 w: F& [- G' Y
Enabled = False# X0 z: [3 X: X! m
TabOrder = 4
) z& T2 w( `4 P; R$ z" S# N- e2 l: D OnClick = btnForwardClick
3 J) M0 i! e ^, Y: W7 L end
8 G/ x6 x7 U) ], [/ e" z object btnRewind: TButton0 b7 P% C5 s9 w$ Z
Left = 376
2 W5 t( w5 V7 k+ y4 B) M Top = 152# b. [+ Y. M" y- {
Width = 75
T+ R9 I/ K7 y+ R Height = 252 S( k7 g' ]- q8 U8 Q4 p3 N+ F3 o9 @
Caption = ‘ 上 一 句( &W)'
2 ]$ w. q% y! C5 A' s$ V9 H. j Enabled = False
* @% \2 C- v0 }: F4 U" R+ i9 B TabOrder = 5/ n! @" O8 R) h# {. _
OnClick = btnRewindClick" U. `/ }# y X2 E$ `5 L9 W1 g
end* \4 V, t f5 S0 x/ P) J
end & N! x4 n1 ]- C: u+ m1 d' p: A
----关 键 代 码 段 如 下: ( H S) d2 i6 Q$ X
---- 1. 朗 读 与 停 止 : n; _: `6 q2 I. Z' J" }7 S2 g2 l
...4 ?: t: C% c: Z; B; s; w
procedure TfrmMain.btnReadClick(Sender: TObject);
3 M( P. r( ]0 \- A( ^" _5 R; {# Z- n begin! K1 w. H' R) O
FISpeech.Speak(memText.Lines.Text, vtxtst_
1 `7 v1 Q$ o0 DREADING);0 x( G- |2 h1 \5 K5 ]& s! n
btnPause.Enabled := True;
4 @' v$ d- M1 J6 R2 R btnStop.Enabled := True;/ [8 Z. G# \6 ^1 ]6 |" ]6 J/ Q
end;# Q9 ^( G: V4 [) L1 p
5 z- a$ P& E3 n z hprocedure TfrmMain.btnStopClick(Sender: TObject);( R( u9 p; d$ P c0 u
begin0 p: a# Q3 q9 k
FISpeech.StopSpeaking;
! U% a( c6 C. B4 y. g2 d, _ btnPause.Enabled := False;
5 }0 M G3 h5 |4 | btnStop.Enabled := False;# F1 T$ R( j4 X5 N
btnPause.Caption := ‘ 暂 停( &P)';
0 v6 f4 L* k! C end;
4 m& Y$ j' Y0 @7 e5 n ...
& Z; W) T$ P9 }----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 & o* R3 N" V3 T
* y- e+ ~8 n7 Y3 [; ^. D( |; T
---- 2. 暂 停 与 恢 复 & H& m' q( \- s
...4 M5 O# u# d+ e7 j- P: R
procedure TfrmMain.btnPauseClick(Sender: TObject);3 [5 p3 m. ~" ^
begin; ~9 t+ e0 b2 r) |1 X' A' o
with FISpeech do) o3 z9 q4 ^3 d0 f
if IsSpeaking then3 U0 X7 N' t" X( N. l
begin
! u9 `! a N1 K' @; M% ] AudioPause;+ f2 K8 `" R* [& [% U
btnPause.Caption := ‘ 恢 复( &R)';
; O7 U# d7 _: @- |2 z end3 ^" n1 }0 F) U' I
else2 k/ R4 i" k* D$ l) G# ^
begin4 o ]( A0 ^; E
AudioResume;) M0 E1 F! r' A/ v
btnPause.Caption := ‘ 暂 停( &P)';
, k+ S X9 i Z9 a2 G end;0 a- x9 ]3 X5 r, I) J
end;. z0 ^! k) x$ N) Z/ B
...
$ P: W1 ]0 \- V4 D----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。 $ [' T+ v9 a0 q* ]- F
----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 ' x! H* r2 M. S+ h
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: . O" b) x, ]. I) B
...
5 B0 ?5 X* ]% FIVTxtAuto = interface(IDispatch)
! L7 }3 u9 R3 W; x K ...7 d4 f: ^8 j/ ~* d
property Speed: Integer read Get_Speed write Set_Speed;
7 Y8 {! E- G5 N9 N property Enabled: Integer read Get_Enabled write Set_Enabled;
. A7 u2 i5 `; q& D4 @- @ g1 l3 s ...6 f9 [4 ~/ o! F4 Z7 H
end;/ g4 _4 a/ ^- z6 [% h3 I5 L3 s
... , B" f$ G! @7 X1 f4 b5 _8 A
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 ' a- {# x" J5 T, g
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 8 \) E8 z0 D0 P" z" m
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。+ t2 k" [7 L# F, h5 u# ~
9 ]7 t7 _1 s1 H) ~, q* H |