|
7 A X" D! k' q q* s5 V华 中 师 范 大 学 卢 小 海(flier@126.com) 9 t) Q- S/ c8 C( d
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 % e$ [) a& h2 s% V1 B6 q. z
* l9 Z- h2 A. p& A1 X6 R
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
. Y5 H' G% J F----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
2 H* W2 I M7 T' T u' i----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 4 [, s k( ^- A1 J# {0 Z) G
----再 在Delphi 里 新 建 一 个Application。
& z/ l! v& v6 U; `# S----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 2 ^9 H. j: E) V9 {' [' T8 s
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
& B! m( |' l2 h$ s" d----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: ; o f- I; n5 D/ B: _9 [
...
/ S7 F' u3 `/ S0 }1 a procedure TfrmMain.FormCreate(Sender: TObject);% }' s% C5 Q( m s/ O2 ?$ {
begin9 h5 |+ M6 _' s; A, i \! v& J
FISpeech := CoVTxtAuto_.Create;
: w4 E% |8 o7 ^; y8 i& [+ h FISpeech.Register(‘Demo Site', ‘Demo App');5 D; v" t4 f' q/ V) w2 L7 g; c
end;, l9 ~( q- o4 D: v x' m
...
9 ]+ x ~+ K& b4 ?----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
3 z, ^/ j* F* W8 m4 K" M----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 0 r5 j' `6 d2 L e! z
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
) H! e T7 @; @) E/ {# m$ }Form 定 义 如 下:
8 D7 e& F# Y9 o3 n0 |' I object frmMain: TfrmMain
* d- E+ F6 B/ F Left = 2962 ~+ v+ i1 m v' {
Top = 187
; h* }9 W1 K; X- H- p/ {+ i; E BorderStyle = bsDialog
8 x, Q9 g+ k0 t# p' S Caption = ‘ 英 文 全 文 朗 读 演 示'0 x2 f! \2 Q% T7 ^: l
ClientHeight = 185
) K, f8 }) F, S$ K4 N% j4 c ClientWidth = 4566 V& G0 S; \# t5 f( j4 F
Color = clBtnFace, v8 {$ Q! A$ ]9 x, ^1 A& Q) H ~
Font.Charset = GB2312_CHARSET9 X3 w# U" w0 H! }
Font.Color = clWindowText
& }% n) ~, K1 S6 a" t# j Font.Height = -12
" T8 K% E" S/ `5 _ Font.Name = ‘ 宋 体'
8 F0 k( l' L7 S9 E) W F' h2 p Font.Style = []
- p, L1 C/ A3 \9 o" v+ F. U# _! h OldCreateOrder = False
3 q+ I2 M$ Q* E Position = poDesktopCenter
L2 j5 V$ c5 V! \# l5 L U% @ OnCreate = FormCreate
# O' A+ K, q+ @& k5 [ PixelsPerInch = 96; @# t A- K/ W; l8 c+ x( b
TextHeight = 12
# k$ W6 B @5 c. a# O% Q object memText: TMemo8 |/ X# M3 Z& T
Left = 84 q; x k9 @7 R
Top = 8+ S* P% y% `8 a/ @+ U
Width = 361
$ h C9 j' O1 H7 w$ j$ i Height = 169
, }! m$ Z- ]) d4 I/ o% M# f, g ScrollBars = ssVertical7 }5 S% e; N s- V
TabOrder = 04 E9 r; P9 I# E/ F$ }9 C
end R( s& e- d8 v8 {) {6 d/ N
object btnRead: TButton
; R" o# x0 h+ z7 n* q7 h) W- p Left = 376$ R. V- s" L+ T( K; {$ Z0 b
Top = 8
4 A: N( b( z: \8 x/ {, N; V Width = 75: c, _3 Q' T/ B
Height = 25' R4 n8 m5 @+ }# a9 H% @; C
Caption = ‘ 朗 读( &R)'
* ]( m- |4 k7 \& u5 y TabOrder = 1
" v T' Y0 R6 A! M OnClick = btnReadClick
4 {" t- R* y. u! ^5 r; {& e end
. |/ ]& s/ a+ a% X object btnPause: TButton
1 k' H0 V2 j1 ~, H( v2 M$ G Left = 3761 ]8 Z$ K' [: i- j2 `
Top = 40$ l+ L3 U; S" r b- s
Width = 75
( i7 ?% a3 Y" K+ ~9 x4 n Height = 250 x2 l" }" d9 W5 `9 U0 x- e! _: R
Caption = ‘ 暂 停( &P)'7 i( C! t$ \6 A1 z' l8 l' ~; z4 p( _
Enabled = False8 n' x' E' C) |5 S7 ^* [; M" ]. x
TabOrder = 26 V/ e' p' u' ~& C: w" a% W
OnClick = btnPauseClick
) {* T |, i5 Q end
) e5 s V1 d( E8 W7 j5 V object btnStop: TButton
% f8 h+ V2 C: @+ q1 J Left = 376
. q0 z% h' v3 F& ^1 e P. } Top = 72* ?* O9 d' P0 u, D& M* T
Width = 75! S7 ]$ O8 ^" a+ ?5 m {; F2 h9 V
Height = 25* U, d- [( u" t J g, [4 M
Caption = ‘ 停 止( &S)'
& S% u8 F3 }, Z$ q2 ^6 j Enabled = False
9 w9 U! k8 }) d$ B' P8 | TabOrder = 3
/ ^. v% j. b0 |+ n% W( F& ] OnClick = btnStopClick# c( q% M" d: i7 |* P+ m
end
8 ^. q: a. R# S! A' ? object btnForward: TButton) W' T; F3 ]6 Z* s6 C5 Q( U
Left = 376
" M( I1 F" W' Z- | Top = 120
/ h9 k: \2 R& G5 s. N7 X4 z Width = 75
- u7 ~# _5 R" C' V* g# j1 D Height = 25
4 E! v! R s& \ n6 l( ] Caption = ‘ 下 一 句( &N)'# \7 J1 }8 H/ i8 { j+ _- Z6 s# g
Enabled = False6 D3 h- n" M# s2 @- X; c6 @
TabOrder = 40 w! K' R. T5 Z0 i! {
OnClick = btnForwardClick( R# `% U' B; o5 e
end
6 B7 \2 J+ R. E, Z8 c+ \: T object btnRewind: TButton
$ N% w+ s+ U5 B/ f2 I) w2 a Left = 376+ Z+ P3 r! m. m5 E: |9 ]7 I9 B
Top = 152
( G. D& U. ]' v. ]- }' Y+ \6 b Width = 75
& c% B% {% u, d4 ?6 [ Height = 25
& u% z4 c8 M) u+ v: o/ e. H Caption = ‘ 上 一 句( &W)'1 G# L9 m9 g: ]0 |+ K
Enabled = False5 `2 m+ \, s9 f2 v u8 } C3 u
TabOrder = 5- S! Q5 \/ ]8 h6 P! x/ x/ G
OnClick = btnRewindClick
5 m0 w( j2 P4 x end$ K* t& A3 Q/ J& a
end
" s) f/ ?; l8 B8 E----关 键 代 码 段 如 下:
% F. A# v9 g9 b1 q0 w2 @% g---- 1. 朗 读 与 停 止
; F& I7 F) E& v6 ^ ...2 D5 [0 @+ y0 e% M3 T/ }) F& s
procedure TfrmMain.btnReadClick(Sender: TObject);. y+ t( s% J0 z1 e0 X; K0 }7 }) X; }
begin
' F7 q: ]4 A2 b0 `) v; N8 R( Y+ V FISpeech.Speak(memText.Lines.Text, vtxtst_
- c) O2 q$ D* l; |9 wREADING);1 d+ A# k+ g$ Q1 p0 Q
btnPause.Enabled := True;6 q4 f* g9 I9 H ]6 Z5 J4 |4 M
btnStop.Enabled := True;. W' c4 m2 ~9 E8 I
end;1 o, ~5 W9 a" v! o6 T7 b
0 ?8 A! X4 j/ x9 a# f X: C
procedure TfrmMain.btnStopClick(Sender: TObject);
! z) j$ p- t$ c begin
& w0 e4 x6 s2 X. O; g3 s FISpeech.StopSpeaking;
6 X" J, m6 U1 u3 k1 ]3 s7 M A1 X btnPause.Enabled := False;0 V' [& ? s0 V) I- s: Q
btnStop.Enabled := False;9 y/ O) _" }) _$ X7 K6 G
btnPause.Caption := ‘ 暂 停( &P)';! [, ], {8 A/ e$ I% ~6 ?
end;+ N! ^1 R! h8 B0 u) a; u7 c
... % A. O5 n! S5 V. b
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
" Y }- Q+ {: A; \
- X- v9 y$ C e, P% J% ^---- 2. 暂 停 与 恢 复 $ g8 U6 M$ j0 x1 x. e. c- Z, S. {
...1 B7 e3 O$ m' x0 D& @1 R8 Q
procedure TfrmMain.btnPauseClick(Sender: TObject);
* a [$ M _9 S6 A begin* y6 s& D" Q3 b7 |! l; m: Q6 G& m
with FISpeech do: _- X5 |/ r, N$ G/ F
if IsSpeaking then0 w8 {, }) s; n9 M
begin7 M( L7 e& e2 l+ }2 E
AudioPause;" o" B( q. K9 _3 q$ q: o
btnPause.Caption := ‘ 恢 复( &R)';6 l& N+ [2 ?# Z( T5 R
end( |) ]( g, a) L8 z) B d
else1 N1 K- w- ?: M
begin
& x" d/ p6 }# _2 R AudioResume;. D' |& B" e$ b1 q* w+ ?; _* ~2 g: e
btnPause.Caption := ‘ 暂 停( &P)';& C: n( [3 D- {+ |
end;
; s" c+ c6 U$ j8 f# m. nend;) b1 T7 x+ A _5 |. R. f
... 4 w) J) M& X$ A" |
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
% W' [1 Y6 | F% }: `. v8 l! ~----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 , K5 ]4 D! {, t1 J& _& H' N
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如:
+ M! ?0 ^8 C7 S ...
; _8 m" y2 A1 ^7 V5 ^9 ]5 VIVTxtAuto = interface(IDispatch)
, g2 f- @: V4 |- k, s# P% ` \ ...
0 ?. n: t/ S% \, R9 g property Speed: Integer read Get_Speed write Set_Speed;
; u. t+ |" ] j( P property Enabled: Integer read Get_Enabled write Set_Enabled;* }! W2 ?, J! J
...
- X0 |% B" @ F3 I3 kend;
2 u9 {- [. @& {3 s4 j- W1 x) s ...
* }1 o+ @8 o( W; s" r8 s( D2 i2 R9 {----即 可 正 常 使 用Speed 和Enabled 属 性 了。 I) }4 y/ x' G( S8 t2 n* J
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 7 [1 d- w" {$ z# U: B; S
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。& Z6 Q1 x u1 U2 Y* B) i7 C: X
+ P4 k0 t6 j" |% @+ q3 S
|