|
6 A3 V4 u; k# {0 z" M+ h
华 中 师 范 大 学 卢 小 海(flier@126.com) ( {1 p% ]3 L; u" l7 m* O' ]% y
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。
& E: t/ ]: u$ v7 ]* k. d) a# s# W/ q2 d. u& d+ _$ a
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 - [; a( Z& M; _$ m* N$ V, }7 U3 M
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
$ N) P7 H% A! g6 l& m% y----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 ! h, P$ N6 K; m6 t3 U. _2 ?
----再 在Delphi 里 新 建 一 个Application。
' ^, |8 u$ s5 l/ p* z) y----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 . @( |9 B$ \8 Z- l+ E3 u! H
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。 ' l! }+ F$ q$ e% o
----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: / R! W5 Z8 g* m: B+ ^; B
...
2 f/ D, s: a7 Q+ W. |% M procedure TfrmMain.FormCreate(Sender: TObject);: C% d. d7 B2 F- [2 t% J' w
begin- v5 L5 M; ~% A) w
FISpeech := CoVTxtAuto_.Create;: D1 u1 Z+ {: d9 l7 V# j- s# u
FISpeech.Register(‘Demo Site', ‘Demo App');% [- h( @7 {$ u! S% F
end;
( b3 ]5 ~' r- e0 b; ~ C... $ T1 y- ~5 z8 }5 T l
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 ! t. ~/ z6 |+ K8 b- A
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 8 m0 D' R, F5 e [
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 1 R# S5 t2 h. t" \0 r# {
Form 定 义 如 下:
! ^8 B+ s+ N- [! q( A- }$ Q object frmMain: TfrmMain
0 C; O# E- ] G- w' y% D Left = 296
/ e0 J7 A: \3 Y& J% k3 s( } Top = 1874 b" k) O3 L( d) o9 I
BorderStyle = bsDialog
' Z" N8 G! G8 A! }8 X" a Caption = ‘ 英 文 全 文 朗 读 演 示'
$ i1 m6 x! i0 D' e; g ClientHeight = 185
$ b5 X/ d, W' u/ q ClientWidth = 456
9 }: x% Y: p4 R# E7 L+ s Color = clBtnFace
" Y- ?! v5 h. @) ]. ` Font.Charset = GB2312_CHARSET
8 L7 i4 D+ H( J! f+ D Font.Color = clWindowText6 N& u& [/ t% q. T2 ?% Y3 t
Font.Height = -12
$ M* N Z6 c- g- ]# R Font.Name = ‘ 宋 体'/ R( W k+ v+ B
Font.Style = []* d7 y- M% n8 G# j! h& H
OldCreateOrder = False* u, |2 l" o& j
Position = poDesktopCenter( V' ? w$ a f
OnCreate = FormCreate2 z( x( {' h2 Y) T/ [/ {, ], V; @
PixelsPerInch = 96+ I H" D' I8 \/ m8 X
TextHeight = 12
# A0 j1 o+ E* S/ c A4 ~: |2 S object memText: TMemo
5 b4 r8 v' V* z& V& Q0 v Left = 81 C, @/ }. m: V: r. t% H8 ]5 h! ~ |/ T
Top = 8' i5 s$ g, `& w- h/ \' I4 S
Width = 3610 L' u2 y/ d: j, F+ j/ N
Height = 1693 Y% Q, W+ w- s) v+ f. K! K
ScrollBars = ssVertical m( C& Y9 ]! j8 F: q# o) N9 }
TabOrder = 07 w/ F' m, h7 c6 P$ W
end/ X; M- ^" S* e; b; Y4 P0 O( Q
object btnRead: TButton
& t0 n9 ^. a. h) F f u( v1 O Left = 376
' w: \* C6 G1 u, u Top = 8! i3 k2 k% g4 u8 V9 k+ ^
Width = 75
, d5 F5 u- `' m1 P; H' w Height = 258 ]1 G( n2 G0 {
Caption = ‘ 朗 读( &R)'
5 `9 Z7 {, U: b* H) Y8 @0 U- p6 } TabOrder = 1
5 q' e1 T3 E- [: a; _ o OnClick = btnReadClick2 x4 v2 T' ^6 W% v) d( e* t
end- O; {" c6 S; @$ q7 ]. e7 V
object btnPause: TButton
6 K' x! w! u" f% e Left = 3768 w' X! D3 ^) j5 o0 H$ C/ h/ H3 U
Top = 401 a1 w! c: |- o! `. s" N% }6 ]
Width = 754 y6 U+ q- R2 E+ H7 v3 E
Height = 25
( J+ U. B% `8 ?; j, S9 j Caption = ‘ 暂 停( &P)') ~: [( q* V0 m, Q% a/ V" R
Enabled = False
) I2 a9 G1 Z; O" C" y TabOrder = 2
! P+ B" U4 U- c( y OnClick = btnPauseClick
; Z2 l2 D% s3 l$ J end
3 F. ?( |' X0 k4 R+ ` object btnStop: TButton3 p- O2 C: j+ B4 f7 K, [
Left = 376, W* F5 r" q- N$ r2 J; o. [# P
Top = 72
$ d) t1 [9 @! e n3 A; G; h+ ] Width = 75) V3 d3 I' f/ B' c+ b/ l9 f
Height = 256 \9 [2 {' P2 O, |
Caption = ‘ 停 止( &S)'
6 M) o* F1 a6 O2 C- ]1 t3 J' o S# s Enabled = False) N( h, I% n% ^$ e( B: l2 O2 I- n
TabOrder = 38 A+ P, M* b7 j( M: `& Q6 H
OnClick = btnStopClick: R( f' j0 G3 ?8 y" N
end
* J9 H) ^+ S! I1 ]. B object btnForward: TButton
! |( K' {2 o6 V/ g: O# Z8 x Left = 376% \* X! T% @" ^
Top = 120
p3 c- C0 \! h: `9 w. I3 B2 a0 F Width = 75
' e @, }) j) @8 y( _7 v& r8 w. c g Height = 25
4 Z- E4 L# X# v) o7 W Caption = ‘ 下 一 句( &N)'# `4 n) Y4 Y4 n# O* c1 y" w1 ?; Q, w0 ?
Enabled = False. X! {- S4 ~; X. z$ N: o
TabOrder = 4
- [( I; @5 H9 H& P OnClick = btnForwardClick
, l0 d% m2 g+ x1 @' ]1 d end* s$ U. q# S- K. g. a5 V( j! A
object btnRewind: TButton
# P- v2 Y! B2 C Left = 376
* j, G% d9 h* T* t- z0 q2 x Top = 152
- A( C2 o/ ?) b2 N9 _4 w0 E Width = 75
' d4 D! M4 B. l( ^ Height = 25
9 p, R4 f( y' W; v! X4 |# u Caption = ‘ 上 一 句( &W)'/ p" ^2 q6 g2 Z- C3 I
Enabled = False" @' V8 s$ S6 P9 L' k8 x
TabOrder = 5& q; F& l, \9 n' B: g/ z
OnClick = btnRewindClick) S0 N0 L( E j5 q
end0 U. e$ ?- b- S; c' Y, U
end
# c0 \3 n" F: \3 y----关 键 代 码 段 如 下: + t& L% J5 f$ X: r& m+ k! v% F- T
---- 1. 朗 读 与 停 止 / |+ @% ?6 A6 }
...
; r2 `4 \; G! K& Pprocedure TfrmMain.btnReadClick(Sender: TObject);' h' s$ p" h! v0 u
begin
9 v* A# E, l0 `3 g$ o FISpeech.Speak(memText.Lines.Text, vtxtst_ # G& G& } a0 ] a
READING);
7 _8 I) Y$ K% I; l, ~6 i btnPause.Enabled := True;5 R% b4 `- O- p9 Z8 L
btnStop.Enabled := True; d) n; r7 p" h. ]; q* s
end;# ]0 L5 [1 J; X6 m/ |% r
, p" I, e; O# p& Z! g5 r; d) e
procedure TfrmMain.btnStopClick(Sender: TObject);2 { S) k( B& k% M. C
begin
% A" r6 R; H1 p( U) F$ q0 M FISpeech.StopSpeaking;
! S4 }# M( Q) ?9 i$ V btnPause.Enabled := False;9 J, b: t* u% P/ B# G
btnStop.Enabled := False;
" ~# z* @$ J* S( t5 e$ v btnPause.Caption := ‘ 暂 停( &P)';& L! M! J( e0 T2 U! e
end;
9 M& S; D, q" O8 C! v6 ^ ...
- L+ Y8 f1 G8 `6 Y, P----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
9 w; {* ?0 {' U) B3 g
' n9 ? E0 `! y" y9 }---- 2. 暂 停 与 恢 复
@+ C: [. p- n$ K C ...
! M. I/ @9 t! }+ M( Dprocedure TfrmMain.btnPauseClick(Sender: TObject);9 F) Q$ E e' e- \ f
begin* R C& X$ v. i
with FISpeech do4 p) E: x- ^; R
if IsSpeaking then- l! t$ H: n. J! J# d: @
begin
: L$ Y/ n6 g3 q+ @ AudioPause;
+ q" i8 I, C$ H9 w R btnPause.Caption := ‘ 恢 复( &R)';+ s* H" Q) ^3 [
end' K$ o* s) r) a, w; K3 ~
else8 _0 S+ I2 |8 a; h5 H9 N
begin3 R! o! k5 ^* O# [, c9 m( f& L
AudioResume;& _' D5 L7 Q3 e6 B9 m
btnPause.Caption := ‘ 暂 停( &P)';8 z! \/ P! W4 ~ Z
end;3 w5 Q% L6 S% v# W
end;
9 t# l) { ]" o... 2 u6 Z3 x0 g) K+ k& _0 b
----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
+ P. `7 h+ n5 f8 N9 F+ i3 ], h----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 . ~' c: Q# s L. G1 w; f
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如:
. X& Z4 U/ @# [ \ ...
1 w9 B3 K9 P* j: ~' ?$ XIVTxtAuto = interface(IDispatch)
1 w0 G( S9 ^0 e! o ...
8 ?, s. ]- |6 [ u property Speed: Integer read Get_Speed write Set_Speed;
, Y" M7 M# a% N( O* A! _ property Enabled: Integer read Get_Enabled write Set_Enabled;
! j( I5 G/ G! c .../ \) U6 w9 f: C) @; \) }
end;
( q c# u2 J9 p* ], ]9 O ... 2 f7 G0 j/ C, \4 j8 ^( j' V0 {1 Q6 B
----即 可 正 常 使 用Speed 和Enabled 属 性 了。
) Z$ B& ~4 h, ?----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 5 I+ G# G4 v. \# X
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。
4 K9 w( I$ b, b4 C4 W' o/ @ - I, y) C5 j4 D: G; I
|