|
6 N z3 s% K% {7 d) s& ^华 中 师 范 大 学 卢 小 海(flier@126.com) " C6 [$ L; I4 C5 Q; y3 N
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 + r- D* ]/ T& ~. o& W2 W2 p# D; e: C, W
9 w3 ?0 a- Y9 a7 \ ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
6 l' O p8 b/ Y: u8 `* U! O; f----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
/ e( t2 \0 w( [3 V; X1 u----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 # Y2 z: c% C' y2 X) x
----再 在Delphi 里 新 建 一 个Application。 ( d. v6 q" [ V9 z
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 ( v; D/ \7 D; w/ M3 \0 q
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
0 k9 k! ?, n: Z6 ~9 b5 R6 ^----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册:
) ]) O9 _: m ~ ...
8 t: |' O8 Q, B+ g3 ? procedure TfrmMain.FormCreate(Sender: TObject);
/ c4 |8 F! L( }: X4 H begin
6 N& A) ~$ Z T FISpeech := CoVTxtAuto_.Create;
! u: m8 q7 ?% L8 w7 f/ x! m; p$ u FISpeech.Register(‘Demo Site', ‘Demo App');2 j$ N, S7 s& h, `0 w- _; [
end;: Y# Z1 {; r) p8 M& d$ c
...
4 G; V$ ] @2 I* Q0 ?% _0 B( {----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 4 O0 c# [6 I% _$ v; {% b6 ?+ _" @
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 ( h; N3 P& ]! O: _5 Y' Q3 u
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。
( Q' J3 I$ {9 u9 i+ g5 v, `Form 定 义 如 下: ) I# F5 | y5 V; n0 `9 f
object frmMain: TfrmMain
7 w+ H1 l# `& s5 O; O Left = 2965 S) v, h P& ~
Top = 187
. T d) t: b I0 X' K6 ^! R BorderStyle = bsDialog3 ~5 r( D# ]$ |
Caption = ‘ 英 文 全 文 朗 读 演 示') s+ f/ n8 P n# ~
ClientHeight = 185
: Z$ E9 V8 {8 R- v% } ClientWidth = 456" S' t, I: ^ M! R5 Z5 K0 q
Color = clBtnFace1 S2 O% y! K" w
Font.Charset = GB2312_CHARSET
8 n3 X/ R8 b' B: N# r1 P1 A' e Font.Color = clWindowText# f: c8 Q1 ^ S r& |& w
Font.Height = -12; g0 C! e. G/ a! A2 o: g- x) w
Font.Name = ‘ 宋 体') J+ M! g, p7 D q$ q3 {
Font.Style = []
B( O: L9 q& J% K% I OldCreateOrder = False
& X( e( K4 O, R/ E Position = poDesktopCenter
, }) `4 s; {! N/ R5 ?2 B( | OnCreate = FormCreate
2 n& z/ L0 R! x0 x* r U+ f PixelsPerInch = 96
6 \5 z& D! Z1 l TextHeight = 12
3 Z8 b9 B: g4 } Q: v object memText: TMemo* U$ q1 W& o* n2 q" a& `0 ]
Left = 8
3 d1 }- o' [7 r3 Y3 h Top = 8
% i! h7 `! f9 n2 W Width = 361
0 g) `' R: p1 `* C4 d) s+ ]( B9 f Height = 169
$ X; I5 h0 W9 ? ScrollBars = ssVertical- p! F8 S7 X0 Y
TabOrder = 0' P+ A' X' [3 \' F3 b9 w
end6 j }7 v6 x/ U+ f
object btnRead: TButton
5 n2 f: o2 c1 x3 A. k0 }+ b6 Y9 d3 X+ b Left = 376" ^3 Z2 x6 N d/ m' {0 P6 ~2 Q# F
Top = 8. K- ?# k, x( _: M
Width = 752 ]4 M6 [3 h9 d, g
Height = 252 `) @+ k8 A1 @1 @
Caption = ‘ 朗 读( &R)'
- g$ _. O- ~- l TabOrder = 1# ]) I5 Y* S& i4 I n
OnClick = btnReadClick
6 z/ }& p! A9 w1 @, b) J# K0 ? end
& y; h# r- x% E) r$ d/ ?( L1 {2 | object btnPause: TButton
" H, i" Y4 |7 ] S7 x% a Left = 376+ }2 f) ^/ r: W: @+ D: @3 W/ E
Top = 408 f5 i/ j; t! r0 w- a9 b0 v1 x
Width = 75# Y% K4 F, m& x& k9 _, J
Height = 25
; g" K( v. d" y+ @1 b Caption = ‘ 暂 停( &P)') e# C6 x/ L- D7 {5 j) L
Enabled = False9 w2 a, R. r; N4 D; N; m6 Z% s8 \
TabOrder = 2
4 j8 v: _; O& l5 k* T OnClick = btnPauseClick. C H1 W7 v( d" H
end; R7 T$ L/ D( ?( R
object btnStop: TButton
' s8 o, s9 `) [/ W( w Left = 376$ P, s/ w; I1 b5 K* G
Top = 72
$ a: z' G5 q$ y# }& a Width = 754 m& G; z! \' Y6 e- }
Height = 25& U/ e( |1 `5 w- v
Caption = ‘ 停 止( &S)') R7 h& H& p e
Enabled = False) }; L& a+ F% Z
TabOrder = 3
) b5 _. N! a% l- o3 ~ OnClick = btnStopClick
/ N: x/ p) ^. L end
4 N/ h5 k& U1 S" A0 _' ^ object btnForward: TButton& T$ S; Q+ ~* }' [: C7 S/ Q! h
Left = 3769 p! \4 R) r9 g+ ?5 a, ?
Top = 120
! ?% K8 u. _- n/ t5 Z/ p Width = 750 t# C9 m- _! q1 j
Height = 25/ h' T$ r' g2 t8 L% x6 D
Caption = ‘ 下 一 句( &N)'
% Z% v, m+ _! R2 Z& l* P Enabled = False
6 l: f% }: O2 {" T2 N TabOrder = 40 y. O) k# ?5 C
OnClick = btnForwardClick
* B6 x; _8 g6 K# C7 P ^ end
0 c9 n- l) R' ?* Y3 \& V object btnRewind: TButton
! A% g$ Q) O+ ^. y- z Left = 376( Y1 v7 q4 h/ C) h
Top = 152
, h- @, a: W: `% n9 E1 s# t* H/ U2 ^1 [ Width = 75: p+ N/ n1 ^2 W1 v" s& @& S
Height = 25
' {) M: ]6 X5 J# E7 ?5 p Caption = ‘ 上 一 句( &W)'
7 D* V: Z2 C& L6 {% o. B Enabled = False! T( R: b2 A: {: |
TabOrder = 5
5 F% W3 D5 E9 e' p OnClick = btnRewindClick: x1 I; n2 H8 f+ a# V& d
end; B* K, X, s& c) I. y6 |) {
end
9 q# S# F+ w3 U& O- K- p----关 键 代 码 段 如 下: 3 G5 @/ ~# m! s, p4 G
---- 1. 朗 读 与 停 止 % H$ ^6 {- E" U' P1 U
..., R8 d2 }: b, j9 V1 @( R5 f5 n
procedure TfrmMain.btnReadClick(Sender: TObject);
) W6 Q: \" ]6 t1 o# {5 N begin6 m9 i4 l! N/ i2 G( c
FISpeech.Speak(memText.Lines.Text, vtxtst_
- t* p. M, }, [- L. [READING);: |+ `5 n* o9 ~% z
btnPause.Enabled := True;
. ]! _# c j6 j& Y- A btnStop.Enabled := True;; E0 {5 S1 n9 l/ Z# F
end;
+ H: @! V6 C J! S% H5 M ! n! v6 U" R1 l/ q3 A' W- `
procedure TfrmMain.btnStopClick(Sender: TObject);- d$ A$ }2 y# M E& L# ]6 F
begin
1 `6 M6 ?* M4 \) H FISpeech.StopSpeaking;
6 j# M7 B; I" [& B btnPause.Enabled := False;
! l* K/ l+ P G btnStop.Enabled := False;2 |$ Z/ O$ y8 h% w2 G' ^) F
btnPause.Caption := ‘ 暂 停( &P)';- P8 X* r4 O: H' o
end;
! |% L, E' o* Z& s3 q. O- V' ] ... . `! p* r: a& l0 N; K' |. m I
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 7 d1 G5 Z8 ]& @- ?
! S1 N6 q- w7 Y8 a9 s1 B
---- 2. 暂 停 与 恢 复
, n& g1 i$ [1 r$ F ...2 S3 o# [: ]; [$ g- J2 u3 q2 B
procedure TfrmMain.btnPauseClick(Sender: TObject);
- U$ z5 |1 W/ y, S5 ?8 s begin
, [( ~8 z0 `- Z/ ]: ?8 k' ] with FISpeech do
7 u2 u! Q* j% Y6 _ if IsSpeaking then9 }% h9 S5 n% _% a$ h, d1 c( S& P: c
begin
+ [ a9 g. {6 Q* q( A3 }8 W AudioPause;6 ^9 D2 H" X: g' V
btnPause.Caption := ‘ 恢 复( &R)';7 ^- N; L2 ^0 G+ a+ C/ N5 |
end
+ Z/ X! b: g5 R8 J2 ~. T- @ else, D7 e/ r4 N- K- c# A' T: n, V5 P; ~
begin4 {& x9 J( ^3 W. r: I
AudioResume;7 ~$ `3 @+ `# \+ h
btnPause.Caption := ‘ 暂 停( &P)';
( \' o: v9 r8 r, \( h4 u end;% A7 N# o* G- `1 x0 ~; Z! G
end;$ q2 A8 H' |# Y5 J8 C
...
# N! u7 N" I" F----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
) Q& c1 ?' E" g2 a9 }----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 7 e1 Y4 {$ y4 r( B& k! H
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: ' }; W M( T* K* d
...; O* A% p: d4 w
IVTxtAuto = interface(IDispatch)
, e; J; e7 \4 x1 D ...3 s5 ~) K$ D! E; I. g/ D
property Speed: Integer read Get_Speed write Set_Speed;
( f1 m1 n2 A" s. F" n% w property Enabled: Integer read Get_Enabled write Set_Enabled;6 L# N3 {( n5 s3 G0 H9 }5 F6 Z
...
7 }! q9 _" ?" _1 vend;
8 I# | {9 _8 M' F0 z ... , d( R1 F3 O- S# X0 R
----即 可 正 常 使 用Speed 和Enabled 属 性 了。 " _- l, m4 z$ p9 y' x) l4 _8 X
----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 ( m- a& T3 \$ z$ E6 a
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。5 i. H0 y" a2 A; N& D
t j0 k" [1 A8 Y) y# t4 |
|