|     Windows  系统调用.COM.微软语言引擎简单应用(C#)   本文主要讲述,如何调用微软的语言引擎...应用场景 如看图识字软件等等....(我可不是作语言软件的、这个子是做着玩的)
 
 涉及技术
 动态调用Com对象(全反射、没有引用com  ocx)
 取得系统存在的各种语言引擎
 使用引擎进行朗读
 使用引擎进行保存声音
 
 
 程序图列:
 
  主要功能描述   实列变量等,构造函授等
 
 取得所有的  识别对象模块集合,放入下拉框
 
 代码
 
 object _spVoiceCls =
 null;    //保存朗读用的 SAPI.SpVoice
 
 const
 int SpFlags =
 1; //SpeechVoiceSpeakFlags.SVSFlagsAsyn
 
 object _oISpeechObjectTokens  =
 null; //保存 SAPI.ISpeechObjectTokens  就是系统有的语音引擎集合
 
 int TokensCount =
 0; // 语音引擎集合 数
 DictionaryEntry[]  _deTokens=null; //榜定下拉框用的
 
 public  MainForm()
 {
 InitializeComponent();
 this.HandleDestroyed +=
 new  EventHandler(Form1_HandleDestroyed);
 }
 
 private
 void Form1_Load(object sender, EventArgs  e)
 {
 
 InitSAPI();
 
 }
 
 
 系统事件:程序加载
 
 取得所有的  识别对象模块集合,放入下拉框
 
 代码
 
 void  InitSAPI()
 {
 //创建语音对象朗读用
 _spVoiceCls  = CreateComObject("SAPI.SpVoice");
 
 if (_spVoiceCls == null)
 {
 
 MessageBox.Show("您的系统没有,微软语音组件");
 Application.Exit();
 }
 else
 {//取得所有的 识别对象模块集合
 
 
 _oISpeechObjectTokens  = CallComMethod("GetVoices", _spVoiceCls); //取得SAPI.ISpeechObjectTokens
 //识别对象集合 Count;
 object r = GetComPropery("Count",  _oISpeechObjectTokens);
 if (r is int)
 {
 
 TokensCount  = (int)r;
 
 if (TokensCount > 0)
 {
 //取得全部语音识别对象模块,及名称,以被以后使用
 _deTokens  = new  DictionaryEntry[TokensCount];
 for (int i = 0; i < TokensCount; i++)
 {
 //从集合中取出单个 识别对象模块
 object oSpObjectToken = CallComMethod("Item", _oISpeechObjectTokens, i);  //返回  SAPI.SpObjectToken
 //取名称
 string Description = CallComMethod("GetDescription", oSpObjectToken) as string;
 //放到 DictionaryEntry 对象中,key 是  识别对象模块,value 是名称
 _deTokens= new DictionaryEntry(oSpObjectToken,  Description);
 
 }
 //邦定到 下拉框
 cboxTokens.DisplayMember  = "Value";
 cboxTokens.ValueMember  = "Key";
 cboxTokens.DataSource  =  _deTokens;
 cboxTokens.SelectedIndex = 0;
 }
 
 }
 
 }
 
 }
 
 
 用户事件:朗读
 
 朗读输入的文本信息
 
 代码
 
 private void btnSynthesis_Click(object sender, EventArgs  e)
 {
 string msg =  rTxtMsg.Text.Trim();
 if (msg.Length != 0)
 {
 
 if (_spVoiceCls != null)
 {
 
 //设置语言引擎
 SetComProperty("Voice", _spVoiceCls,  cboxTokens.SelectedValue);
 //调用Speak 函数,msg 是要播放的文本,1 是异步播放,因为是异步的  com 对象不立刻释放
 CallComMethod("Speak", _spVoiceCls, msg,  SpFlags);
 
 }
 }
 
 }
 
 用户事件:保存声音
 
 将输入的文本信息生成音频文件保存到文件
 
 代码
 
 
 private void  Save()
 {
 string msg =  rTxtMsg.Text.Trim();
 if (msg.Length != 0)
 {
 using (SaveFileDialog sfd  = new  SaveFileDialog())
 {
 sfd.Filter  = "wav 文件 (*.wav)|*.wav";
 sfd.RestoreDirectory  = true;
 if (sfd.ShowDialog() ==  DialogResult.OK)
 {
 /*
 Enum  SpeechStreamFileMode;
 SSFMOpenForRead =  0;
 SSFMOpenReadWrite =  1;
 SSFMCreate =  2;
 SSFMCreateForWrite =  3;
 
 */
 
 int SpFileMode = 3;//  SpeechStreamFileMode.SSFMCreateForWrite
 
 object oSpFileStream = CreateComObject("SAPI.SpFileStream"); //创建 SAPI.SpFileStream
 
 object oSpVoice = CreateComObject("SAPI.SpVoice"); //创建 SAPI.SpVoice
 
 
 try
 {
 CallComMethod("Open", oSpFileStream, sfd.FileName,  SpFileMode, false); //打开流
 SetComProperty("Voice", oSpVoice,  cboxTokens.SelectedValue); //设置 Voice 属性,让谁朗读
 SetComProperty("AudioOutputStream", oSpVoice, oSpFileStream);  //设置流
 
 CallComMethod("Speak", oSpVoice, msg, SpFlags);  //调用 Speak
 
 CallComMethod("WaitUntilDone", oSpVoice, Timeout.Infinite);  //等
 CallComMethod("Close", oSpFileStream); //关闭流
 
 MessageBox.Show("保存成功");
 }
 finally
 {
 Marshal.ReleaseComObject(oSpVoice);
 Marshal.ReleaseComObject(oSpFileStream);
 }
 
 
 
 
 }
 
 }
 }
 
 }
 private void btnSave_Click(object sender, EventArgs  e)
 {
 
 try
 {
 btnSave.Enabled  = false;
 Save();
 
 }
 catch (Exception  ex)
 {
 MessageBox.Show(ex.Message);
 }
 finally
 {
 btnSave.Enabled  = true;
 }
 
 }
 
 调用com组件,功能函数
 
 自己写的一些帮助函数可以方便调用反射,要不太郁闷(如果是VB  就不用如此费尽了)
 
 
 #region 调用com组件,功能通用函数
 /// <summary>
 /// 设置属性
 /// </summary>
 /// <param  name="name"></param>
 /// <param  name="o"></param>
 /// <param  name="vlaue"></param>
 private static void SetComProperty(string name, object o, object  vlaue)
 {
 Type t =  o.GetType();
 t.InvokeMember(name, BindingFlags.Instance  | BindingFlags.SetProperty,  null, o, new
 object[] { vlaue  });
 }
 /// <summary>
 /// 取得属性
 /// </summary>
 /// <param  name="name"></param>
 /// <param  name="o"></param>
 /// <returns></returns>
 private static object GetComPropery(string name, object o)
 {
 Type  t =  o.GetType();
 return t.InvokeMember(name,  BindingFlags.Instance | BindingFlags.GetProperty,  null, o, null);
 }
 /// <summary>
 /// 调用方法函授
 /// </summary>
 /// <param  name="name"></param>
 /// <param  name="o"></param>
 /// <param  name="parms"></param>
 /// <returns></returns>
 private static object CallComMethod(string name, object o, params object[]  parms)
 {
 Type t =  o.GetType();
 
 return t.InvokeMember(name,  BindingFlags.Instance | BindingFlags.InvokeMethod,  null, o,  parms);
 }
 /// <summary>
 /// 创建 com  对象
 ///  </summary>
 /// <param  name="FromProgID"></param>
 /// <returns></returns>
 private static object CreateComObject(string  FromProgID)
 {
 Type comType =  Type.GetTypeFromProgID(FromProgID);
 object rVar = null;
 if (comType != null)
 rVar  =  System.Activator.CreateInstance(comType);
 
 return  rVar;
 }
 #endregion
 
 释放com对象
 很简单的就一行即可
 
 代码
 void  Form1_HandleDestroyed(object sender, EventArgs  e)
 {
 //释放com对象
 Marshal.ReleaseComObject(_spVoiceCls);
 
 }
 
 
 说明 关于 SAPI 对象的具体情参考,msdn Microsoft Speech SDK 部分是英文的帮助(VS2003 和 VS2005  的都有,ms 网站上好像也有),我英文也不好没法翻译抱歉,我用的这些函数有的是在 ms 网站上看到的有的是自己用对象浏览器慢慢找的....
 |