|
5 E; g9 F$ u3 q$ \华 中 师 范 大 学 卢 小 海(flier@126.com) * s% H6 }& K8 G+ D- r; t {
各位朋友,请加入本站邮件列表,你将得到本站最新更新及动态。 0 J6 i9 ^. N' B8 d# T/ ^
/ q/ N, ?1 W! E ---- 金 山 词 霸2000 的 英 文 全 文 朗 读 功 能 相 信 一 定 给 尝 试 过 的 用 户 留 下 了 很 深 刻 的 印 象, 而 作 为 一 个 程 序 设 计 者, 你 一 定 也 想 在 自 己 的 程 序 中 加 入 类 似 的 功 能 吧, 因 为 那 将 让 自 己 的 程 序 增 色 不 少。
! n2 j0 z6 Y0 f/ Q( q----其 实 这 并 不 是 一 件 困 难 的 事, 因 为 金 山 词 霸 实 际 上 也 只 是 直 接 使 用 了MS 的TTS(Text -to -Speech) 技 术 而 已, 通 过 对MS Speech API 的 编 程, 我 们 完 全 可 以 实 现 比 其 更 强 大 的 功 能。 下 面, 让 我 们 在Delphi 环 境 下 实 际 尝 试 一 下。
& h- K: q3 N$ `$ U# ^2 B! p----首 先 从 金 山 词 霸 的 光 盘 上\ciba 目 录 下 运 行 并 安 装mstts.exe(MS TTS engine) 和spchapi.exe(MS Speech API)。 ! d. Q1 M% H$ g
----再 在Delphi 里 新 建 一 个Application。
3 @, m9 N: h- V7 f, W7 \ d----然 后 从Delphi 的 菜 单Project/Import Type Library... 中 选 击Add..., 浏 览 到Windows 目 录 下 的Speech 子 目 录 里, 打 开vtxtauto.tlb, 可 以 看 到 下 面Class names 中 会 出 现 我 们 需 要 的 接 口 的 包 装 类 的 名 字TVTxtAuto, 注 意 对 话 框 底 部 的Generate Component Wrapper 需 要 被 选 中, 点 击Create Unit 就 可 以 打 开 一 个 名 为VTxtAuto_TLB 的Unit。 ) v' D$ j4 s9 i- E7 r
----至 此, 我 们 就 可 以 开 始 实 际 编 程 了。
$ p+ e% M' d8 ^2 _6 h----首 先 在Form 的OnCreate 中 对 需 要 使 用 接 口 初 始 化 并 进 行 注 册: . a; D$ F( w- n
...
2 e3 P7 ^1 ?3 l: t+ j procedure TfrmMain.FormCreate(Sender: TObject);; Q6 U/ q6 O7 s
begin
7 u- g, _) a+ O6 ?1 p F FISpeech := CoVTxtAuto_.Create;% `0 p! ?8 K4 i$ A0 U- I4 {
FISpeech.Register(‘Demo Site', ‘Demo App');
! z0 G9 {1 s9 X) l end;
% v5 v2 w7 m% f... : p, [4 B2 j& u2 D8 W' [* Y2 O
----由 于Delphi 对 接 口 进 行 了 良 好 的 包 装, 因 此 只 需 直 接 建 立 包 装 类, 其 他 后 台 的 操 作 如 接 口 的 查 询、 释 放 等 交 给Delphi 在 后 台 自 动 完 成。 $ W0 C- E( E- z- N q# b
----注 意 这 里 的Register 操 作 是 必 不 可 少 的, 因 为 可 能 有 多 个 程 序 不 同 设 置 使 用TTS 引 擎。 : f2 b9 e- X/ f( _+ \: [- q
----然 后 在MainForm 上 放 一 个TMemo 和 若 干 个 TButton, 并 在 其OnClick 中 加 入 对 应 的 代 码。 ( y( B5 K. Z8 ?# o! R1 I `2 d
Form 定 义 如 下: % o: H% i/ [6 x: G: ~
object frmMain: TfrmMain: K1 {- i3 \3 H4 d* `9 N8 R
Left = 2968 [: l1 E8 ^% D% }$ A7 \. `
Top = 187
; f/ \. k) Y# W1 W BorderStyle = bsDialog* Z- J7 _# ]& T) a, U7 b
Caption = ‘ 英 文 全 文 朗 读 演 示'5 i0 q$ n1 @ m1 _4 j- p
ClientHeight = 185
9 R; y' O2 i& n. f ClientWidth = 4569 ]! C6 X3 z$ {$ X" Y1 W# Z& e
Color = clBtnFace Q: t t8 U3 b
Font.Charset = GB2312_CHARSET7 ?0 r3 i; u* a7 J" r n! f3 F# D: ^
Font.Color = clWindowText
" |# ] D0 Z# V' ? Font.Height = -12
2 S2 h2 K, Z) f: E Font.Name = ‘ 宋 体'
) W3 H9 Z$ d$ g1 Y1 Z) G$ W( a7 D Font.Style = []
0 Y/ z$ M# I( I. m. N" E OldCreateOrder = False" j( k6 L* }/ n' s
Position = poDesktopCenter
# e1 ]% k8 m' T' l4 f0 |6 B OnCreate = FormCreate% X7 U4 }) V3 ?: M
PixelsPerInch = 96
7 G9 z0 X. Z# N& R( I- w, _ TextHeight = 12
& f9 q, N7 G1 B* k: N$ A3 g object memText: TMemo
9 D* X6 R# |1 B3 C' k @% B Left = 8; \- G/ K' Z9 ^7 y
Top = 88 l, h% k3 x! W2 P. i
Width = 3615 P1 C5 U! l2 C) ~
Height = 169
/ P; k! X8 l- q( \9 ^7 n% E ScrollBars = ssVertical8 t1 i! u. B. x1 o; T* I
TabOrder = 0. a1 Q7 g' `0 E6 {; x% E
end! V& @# r) _! }
object btnRead: TButton
9 `0 d1 q) a! |% O+ P: [ Left = 376% c5 H( D. I9 Z* Z: t3 m
Top = 8
/ R9 }: }0 r# |' R Width = 75" c5 Q( X( w9 p
Height = 25
# c! I8 r" }5 J* F/ K3 V, T. I Caption = ‘ 朗 读( &R)'6 N h }' u* |$ i3 J1 u! R- \8 a
TabOrder = 1" O, l9 p; E; V8 l
OnClick = btnReadClick
3 \- ~0 T/ }: S A. z) s. d end
8 V7 z# q% T. T. h% g6 B" x; D object btnPause: TButton5 T! ^2 k {& U
Left = 376
5 f% A' d) a/ V- U Top = 40
% l% Z1 @3 ]+ [, _8 Z; J# G Width = 75* \' Q- H: z' w) _
Height = 25 Y& ]( q/ I; p! w" M. }9 P
Caption = ‘ 暂 停( &P)'4 D" c0 W: r( b6 d
Enabled = False
7 K" A. v: w; j' t$ K1 q, U TabOrder = 26 N) q( D8 U6 @9 \) O
OnClick = btnPauseClick
3 k3 T' G4 P* T4 R# I+ ^" s* V end: J* D: E/ O7 n$ |1 O; p
object btnStop: TButton" O' i/ O# l4 D3 A" }/ E
Left = 376/ ^# `# e! M$ }6 O* {! r7 l% a
Top = 72
2 z, O" {1 u9 [* v1 w2 u+ A Width = 756 t$ \8 n+ a1 M5 a6 k" I
Height = 25
4 M. W. P' P8 ~. s0 h O+ g, p% m! o; ] Caption = ‘ 停 止( &S)'* j) A4 a- \" t8 x" M
Enabled = False) v9 ~3 z' |9 j; R) O3 G; [; X% t6 J
TabOrder = 3
& ^5 D: T2 \+ } OnClick = btnStopClick
& f. ~9 X- h/ q7 x0 A, _ end
|- g* @( X8 Q2 x' a9 p+ D3 F1 h object btnForward: TButton4 m+ w1 Y r% Y9 E& I
Left = 376& G; Y+ y Z/ ~7 U& c: y
Top = 120
2 A8 l5 x' Z& s8 Y2 }. Y: s Width = 75
) y/ L) X4 `1 {6 m, M Height = 254 K U3 ~4 ^7 O- m3 N0 P% `5 j, a
Caption = ‘ 下 一 句( &N)'
0 m# i2 r0 [" U& H6 U5 g. q; Y Enabled = False! g- n3 \7 h/ Y# ]: I
TabOrder = 4
, c7 l) {9 R" _; z4 V, J! x" v OnClick = btnForwardClick
( [5 S7 g; ?3 w ?+ H1 p end) l1 r* ?+ P6 R. }! B2 Z! f# |
object btnRewind: TButton; ?5 x: s" j% q0 e5 j
Left = 376
. l$ j6 Z# R. {7 O8 V3 ], j Top = 152- Z7 s' G8 b& P. U
Width = 75
9 V5 W ~0 {$ [+ J5 Z Height = 25+ R* X# l8 h5 b% A8 Q" v
Caption = ‘ 上 一 句( &W)'
2 c! [9 J$ V; T n Enabled = False7 N# m& q$ X0 D0 f1 Z0 r- e
TabOrder = 5
" o8 q" W/ M6 m5 k `- [, i OnClick = btnRewindClick
8 U0 `1 N @+ }& ]! A# X4 F end
M$ [% u5 r, O. ?- ?3 s* ]6 } end
# }- A, z- p& Y" N" }. i A7 {) x----关 键 代 码 段 如 下:
* P5 L% ]! a3 Q3 _---- 1. 朗 读 与 停 止 7 O# W6 L/ ]3 T5 c& j' S
...; T: D# l3 E' q) f
procedure TfrmMain.btnReadClick(Sender: TObject);
3 b) g% z) M1 j5 L5 {) G% @ begin; N* s3 `( O4 l, f" b2 g8 j3 O9 l
FISpeech.Speak(memText.Lines.Text, vtxtst_
3 M2 \" T: m; dREADING);( N7 M6 B1 i$ {& v7 y
btnPause.Enabled := True;
4 z, r; i8 q, q# I% | btnStop.Enabled := True;
7 g$ {# o- V1 T* ] end;4 p9 ?# `9 v4 L% r
0 s# e* N$ {( f! m9 d% k6 {
procedure TfrmMain.btnStopClick(Sender: TObject);
) q/ H/ U( J* T& F% c begin
+ ?5 B- @9 v# W/ F' N' U6 | FISpeech.StopSpeaking;
. j% ?2 `9 [6 O, i7 h btnPause.Enabled := False;
0 \3 `1 i" O$ i, B# b- T btnStop.Enabled := False;( Q; j1 H9 P/ u8 w
btnPause.Caption := ‘ 暂 停( &P)';# D! x7 y3 A# e9 o& D6 U" s) z
end;( l; I5 N& D6 v. A& }- T
... 4 q3 O" b! t- `+ |- P( \, B- g
----Speak 成 员 函 数 的 第 一 个 参 数 向TTS 引 擎 传 递 需 要 朗 读 的 文 字, 第 二 个 参 数 由 指 定 朗 读 时 使 用 的 语 气 和 优 先 级 的 两 个 符 号 合 并 而 成。 / W2 v' j* `5 w
$ K2 u) ? n, w8 s; [- ?---- 2. 暂 停 与 恢 复
7 z' g- t% t* y' I4 w3 k ...
! @9 P# E0 D; rprocedure TfrmMain.btnPauseClick(Sender: TObject);
* x# s7 G; h) Y% \. a) b* N4 i begin- N9 R! t0 K4 k! ^5 d; O
with FISpeech do
& {, Y q5 u2 l6 X: [2 u( q if IsSpeaking then
5 i0 Z7 C W0 Z4 W0 M begin" i+ V1 F' n) w. N6 _9 I& p* ?
AudioPause;
4 h6 A g/ _, b9 D0 }' L: I. g btnPause.Caption := ‘ 恢 复( &R)';9 d% Y% @' r5 Q! R
end! Y0 V4 q4 M: I6 b( H! K7 r
else, [8 ^% i$ J. F5 A c
begin. s. g1 I# }6 y
AudioResume;
% J( U( Q, \# H: C& g# b% P' q6 C btnPause.Caption := ‘ 暂 停( &P)';
* K8 l3 U7 N' t& Y6 O3 D# ~( I end;3 E0 m- s6 p; O* A5 i0 J
end;
- w, a+ B" Y# R; T...
7 X5 c3 {9 U# [5 K" `----这 里 通 过IsSpeaking 属 性 可 以 取 得 当 前 状 态, 然 后 通 过AudioPause 和AudioResume 暂 停 和 恢 复 朗 读。
* H( y* E: r2 Y9 G- G# B& O: N, N----另 外 用 成 员 函 数AudioFastForward 和AudioRewind 可 以 向 前 和 后 跳 过 一 句 朗 读, 通 过 读 写Speed 属 性 还 可 以 取 得 或 设 置 朗 读 的 语 速, 单 位 是 字/ 分, 缺 省 值 为170。 + N8 m% {' s( Q: M4 l
----注 意Speed 和Enabled 属 性 缺 省 设 置 是 只 写 的, 但 实 际 上IVTxtAuto 提 供 了Get_Speed 和Get_Enabled 函 数, 所 以 我 们 只 要 把VTxtAuto_TLB 单 元 中 的 声 明 修 改 一 下, 如: $ E. E' ^4 r1 s* {5 X5 G- g1 G! D Z
...0 W9 W @" P7 y3 \4 h; R
IVTxtAuto = interface(IDispatch)
2 ]0 h- O) U- C+ M/ q ...5 D$ S2 Y/ O, |3 {. ]
property Speed: Integer read Get_Speed write Set_Speed;* v& J( a; x j
property Enabled: Integer read Get_Enabled write Set_Enabled;
1 y; W7 I; Q1 f ... u6 q0 c ]# G8 u: U* m
end;% K" b$ }( N% v ^0 s. T
... ! x4 S3 s* ^( Q6 a: G- i4 ?
----即 可 正 常 使 用Speed 和Enabled 属 性 了。
2 C& m4 \ j8 ?3 C7 G3 }----至 此, 一 个 简 单 的 英 文 全 文 朗 读 器 就 完 成 了, 有 兴 趣 的 朋 友 可 以 为 其 加 入 监 视 剪 贴 板, 热 键 激 活 等 功 能。
( Z- @- o( C! t0 Z5 m$ q----本 文 程 序 在Win NT/98 + Delphi 4/5 环 境 下 调 试 通 过。! h- i3 i5 d3 V4 K5 F8 w9 v) h
) Y: V: G7 ^- y! A& `: w# ? |