|
1 S) I7 j5 n6 X) P$ e2 C华 中 师 范 大 学 卢 小 海(flier@126.com) ( e+ ^4 x, i; D4 d, n) b2 w
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 7 R3 K! ?2 f/ l$ u
' k& d; M8 `. z# S4 X" w8 o
---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。 " d) D' V+ d, t# N& R. Z# z
----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
# v9 u5 G5 L9 j1 ^7 C- ?8 t----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 # _2 B/ q% \( C+ A( r
----再 在Delphi 里 新 建 一 个Application。 ; Z, `4 K- X! j
----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 , G) G; w' n# Z4 M
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
# {7 r# Y8 g8 b----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: ; F$ {: r+ e$ O) |8 c- j; k
...8 b! j9 p7 E0 R, Z/ M
procedure TfrmMain.FormCreate(Sender: TObject);/ h: o. u3 V5 d: s) {0 C
begin
* m& x* R5 Y3 }" d4 u FISpeech := CoVTxtAuto_.Create;' J- Z. ` q1 i% L9 h8 D
FISpeech.Register(‘Demo Site', ‘Demo App');
. {" H. r( f2 C$ R: @ end;+ q3 H p7 c1 ?7 |! o4 R4 @" e( p: q( T
... 1 l! O: v" L: U% h4 p
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。
# L! D# @! I# Y9 g) G. T----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 ! j: B: \( {+ U6 B
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 1 |; ^! c3 x' q- W4 h/ l
Form 定 义 如 下: ! O0 }9 l: G9 g: Q3 E: n- y+ z. Y
object frmMain: TfrmMain- n" |7 m: f7 l% c4 |
Left = 2967 W+ C) M1 F* X% l9 l
Top = 187
d; V* Y4 A7 S- L/ ]( q& I4 Z BorderStyle = bsDialog
5 ]& p9 }5 A2 C. t$ f Caption = ‘ 英 文 全 文 朗 读 演 示'6 Y; s, r9 B5 ]6 [/ H
ClientHeight = 185
9 S; l; }2 R& E ClientWidth = 4564 O% X- I7 W3 e$ W
Color = clBtnFace6 ~: a- b1 A- j& L/ I ?3 g2 z& v# M
Font.Charset = GB2312_CHARSET* j, p3 n$ ?: S- f. t
Font.Color = clWindowText
/ D) \7 p. d- |! s' P* _" c" |* T5 F Font.Height = -12
& G7 f# u- G# @* U0 O* ~# D Font.Name = ‘ 宋 体'
g- M2 i5 W. A& g* x3 P& A Font.Style = []) U0 n7 }$ Y- @9 I! f+ ~- J" c4 [
OldCreateOrder = False9 b7 G' k+ k# `1 w
Position = poDesktopCenter9 V$ _# O- x" A6 d
OnCreate = FormCreate$ Q, Y; B8 U( A# Q# D
PixelsPerInch = 96' O& W0 x, S$ y- @$ m: J1 r3 x
TextHeight = 12+ p9 z; s& K# X7 g4 t9 ]3 t! M
object memText: TMemo
+ @ d" y( q& X1 W( P( t9 G9 _ Left = 88 j4 c7 D1 ^% W$ Y, m H6 D3 ?# l
Top = 8+ d1 Y K: v' o3 g6 S7 G
Width = 361, h0 v+ g5 ?" y# V8 F0 u$ h
Height = 1696 V, L( [* C) r- D# t& C4 x
ScrollBars = ssVertical
+ W& a7 g) x0 B* L: C' N" h TabOrder = 06 V$ @) k* E7 d& x8 P3 u* m
end
0 I2 r4 ~+ `! Z G0 ]9 v& D object btnRead: TButton
5 x* P( e9 z1 z2 {3 r. J Left = 3763 p8 i5 b! I1 p6 }. H( b
Top = 8
5 @9 [/ ^7 F) D8 k9 t Width = 753 g0 I" K/ L8 _' ]
Height = 25
5 R6 y. X% }% N% \ p Caption = ‘ 朗 读( &R)'; I* k+ l% L' r3 G% g) e9 a
TabOrder = 1' Q( g0 ]; P9 b: r
OnClick = btnReadClick$ A6 F) d& x+ x( P9 t9 d+ i2 [6 {5 K
end
Z) R5 c- K. o( h object btnPause: TButton8 M4 B/ c! N3 y2 L9 C7 _8 }, c
Left = 376
/ L6 N! M2 Y p Top = 40+ S0 k8 r! ]5 P/ v5 f/ l
Width = 75
3 V, n8 V) Y+ a4 m- l Height = 25
$ z# I5 i: o4 [# T) n- E Caption = ‘ 暂 停( &P)'0 N0 X2 u: ~5 f! @ }
Enabled = False
. o" n1 Q9 V8 N; n: z/ b- y TabOrder = 2" z+ g- f: ]( y2 J* C6 _; v' N
OnClick = btnPauseClick
4 b$ y% Z! I8 E( ^! j end Z6 [# G8 u% F) x
object btnStop: TButton
4 l/ L% i# l% `8 s0 f) C Left = 376% B$ M0 F N5 Y; f2 h5 i2 f! Y
Top = 724 J; B/ z* r% Q; Z: B. C- r7 b5 I
Width = 75
' |) G! U9 d$ Z Height = 25
/ U2 t$ V" W" G. m+ h) {# E Caption = ‘ 停 止( &S)'8 }# r' v5 C& P) W' b! R# K
Enabled = False Z3 p- V+ M" E) j$ C( @
TabOrder = 3
. I+ |* S' \+ @5 w5 P, H OnClick = btnStopClick+ g9 W d2 {: t2 [7 \
end2 V# |& ^6 w4 D6 A
object btnForward: TButton ?; t2 Z. f- U: N5 ^1 {6 _* |1 P
Left = 376: H( z" ]9 g& T. k4 `
Top = 120" `" V% }- J% ]* z: D8 z' j8 J
Width = 75
- ~9 x: x% e4 G5 z9 K. K6 j; g. \ Height = 25
8 t2 d9 n, d1 c, l Caption = ‘ 下 一 句( &N)'7 B! p# p" d$ f
Enabled = False
& m& C |. b" G4 x TabOrder = 4
2 Z/ O, b0 y1 u) t OnClick = btnForwardClick
5 V( Z# ^' G, g" a% b5 k end
0 E8 I, ?! G/ I object btnRewind: TButton" ]* E9 d9 A' _) ~. \5 e, |& e6 t
Left = 376& v; |& I, D9 ]3 A' Q
Top = 152
& V1 e" ^+ R* [& o4 m- e# L5 a Width = 75$ z& i) A( v U/ X
Height = 25* R% k' l: Y, Z/ u3 R
Caption = ‘ 上 一 句( &W)'
- ?. s |2 ? {+ O+ E( ? Enabled = False9 {% b+ ~9 S* m. z4 D
TabOrder = 5
5 ?% W' }6 k& F/ w- G OnClick = btnRewindClick) X K3 i- a8 m# ]
end; v- r# @2 V& {) v" J
end
9 C) V: U8 y9 p/ P----关 键 代 码 段 如 下: + }& `# E7 b9 _* r: k
---- 1. 朗 读 与 停 止
! p2 P' O# A; w) E! [ ...
r) H v. `. _2 kprocedure TfrmMain.btnReadClick(Sender: TObject);% q3 v% R9 S+ R+ m9 k
begin
( g' j: t: B1 d+ y9 R0 O FISpeech.Speak(memText.Lines.Text, vtxtst_ ! T# ]& @% D5 y. S* W7 r) R0 {' p
READING);+ Q5 }* l( j8 b3 C& j# `6 E
btnPause.Enabled := True;: L3 E8 a* k* q5 f1 i0 V
btnStop.Enabled := True;& k% v; r2 Q/ @8 L- W& Q$ Q. o8 c d
end;7 {5 K3 o' m! [- U0 r, Y x1 V( L
7 @- A! G5 U- P+ V' L$ c4 Xprocedure TfrmMain.btnStopClick(Sender: TObject);
- I3 n8 j9 B$ @5 V3 J4 [: K begin& [) p% w( _8 h8 J8 @6 r" I# d/ V
FISpeech.StopSpeaking;
3 b }$ d9 m3 I( d3 G; y btnPause.Enabled := False;
/ K. }4 @9 l1 O3 w btnStop.Enabled := False;
r# {+ a" R( C9 f, [, A btnPause.Caption := ‘ 暂 停( &P)';& W" e5 A- s* z B. T' u5 ?9 n
end;
3 |& l4 e- O/ n4 n! X ...
# C9 [, H/ L& R7 x' o+ ?) H# I----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。
0 i X9 F ]6 h, X
9 W' {$ j/ Q2 u" p* O5 a---- 2. 暂 停 与 恢 复
8 [ }' m4 v$ T0 @$ M! F ...' Z7 r& E" M# e" x
procedure TfrmMain.btnPauseClick(Sender: TObject);
# r$ R a& A; Q9 j' x9 m# ? begin' ~; A9 q' A+ w& i
with FISpeech do
1 h& z9 ]$ A. ^2 x2 U1 @1 k if IsSpeaking then
* S% M4 Y4 S( B+ r( W% X2 C* Y begin( z0 o3 C; X4 v! U. x
AudioPause;, h0 ?5 @, e/ i2 V5 i
btnPause.Caption := ‘ 恢 复( &R)';7 V5 F" z) H+ m2 U9 H
end) O; f( b* e! o# V
else0 ~' ?* `0 O3 A. p2 c. h1 o# `
begin) e) X! q6 \+ y' v1 Y4 v6 Z
AudioResume;8 S& w" A2 f1 f! A4 p5 f2 Y Y
btnPause.Caption := ‘ 暂 停( &P)';
, {7 S; }' h: H( A3 }( l end;& x: w7 Q; |) ~& I' l! u' t- b4 _
end;3 X1 i/ `) V0 u" W2 I. b
...
" l8 s2 m$ \) o, N4 M" } U8 C----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
: b3 j" p$ B+ P+ v- }2 B----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 ) t) ^( I1 {& @ S3 p6 r
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: 3 e: o! b! t+ w0 w/ m, k4 x
...: b1 M: ]; c# i3 }. v
IVTxtAuto = interface(IDispatch)
. c4 ~4 S: k# Q4 ` ...* x, w: C) f2 A/ E$ i
property Speed: Integer read Get_Speed write Set_Speed;
T2 }" W* l* A& p, H- e& ]2 n property Enabled: Integer read Get_Enabled write Set_Enabled;
1 R" t: V/ {+ g/ v2 X" E6 ? ...
' `- {+ {6 R# ^& Z: d3 p. _end;
) y# @7 A. x* M G% p ...
; n. W; i& I# P( l% m( |. @2 c----即 可 正 常 使 用Speed 和Enabled 属 性 了。
8 E7 g" Q) @3 M( G4 h8 i) s/ i5 e----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。 1 A+ s0 w2 K. N9 S3 k
----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。1 J, s" \4 N; v! G: k2 N p" D
- ~- u3 D5 z$ M; L: x" N g |