65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Word Automation 和 Text-to-Speech 控件创建字典

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.40/5 (11投票s)

2002年12月18日

3分钟阅读

viewsIcon

152509

downloadIcon

3586

基于 MFC 的 MS Word 拼写检查器实现。

Sample Image - dictionary_automation.gif

引言

每当我想知道一个单词的意思时,我通常会打开一个 Word 文档并搜索同义词。 所以,我想只调用词库,而不打开 Word 文档,那就太好了。 甚至让我的电脑发音这个单词就更好了。 自动化是第一个问题的答案,而 Microsoft 文本到语音控件解决了第二个问题。 我认为,来自 VC 的 Office 自动化是最缺乏文档的主题之一。 但是我们获得了大量的 VBA 文档。 让我们看看我是怎么做的。 我将向您展示一个循序渐进的方法。

步骤 1

打开一个基于 MFC 对话框的应用程序。

第二步

创建如图所示的控件。

步骤 3

打开类向导。 在“自动化”选项卡中,单击“添加类”-->“从类型库”。 打开文件对话框会要求提供“*.olb”文件。 您可以在“Microsoft Office 目录”中找到它。 对于 Office 2000,它是msword9.olb。 对于旧版本,它是msword8.olb。 如果找不到它,请搜索它! 但是您应该找到它,否则我们无法继续!!! 找到类型库后,打开它,会弹出一个新窗口。 它要求我们选择 Word 公开的自动化对象。 对于我们的目的,我们可能不需要所有这些。 因此,如果您不确定要选择哪些类,请选择所有类,然后按“确定”。

您可以看到正在将 2 个文件添加到项目中 - Msword9.cppMsword9.h(在旧版本中,它是 Msword8.cppMsword8.h)。 检查添加的新类。

正是 _Application 对象创建了 Word 应用程序实例。 Documents 类枚举文档,而 Document 类用于处理特定文档。

步骤 4

我希望您知道 Word 自动化需要哪些对象。 (如果您愿意,可以跳过此步骤。)如果您不确定,可以通过使用 Word 宏来获得一个不错的想法。 看一看... 打开一个新的 Word 文档。 选择工具--->宏--->录制新宏。 将宏存储在新文档本身中。 新的按钮集将被添加到工具栏,并且鼠标指针上会附加一个盒式磁带。 现在输入一些单词并选择它。(如果鼠标不太友好,请使用 shift+箭头键。) 选择工具--->语言--->词库。 现在,词库会显示同义词。 选择“替换”或“取消”。 在工具栏中,您可以看到宏的“停止”按钮。 停止它。 现在,如果您打开工具--->宏--->宏,您可以看到宏列表。 选择 Macro1(或您命名的任何名称),然后单击“编辑”。 它将在 VB 环境中打开。 您可以看到 Selection 对象被频繁使用。 词库窗口也正在从 SelectionRange 对象中被调用。 在您的应用程序中,如果您从 Range 对象调用 CheckSynonyms(),则可以显示完全相同的词库窗口。 但是我们希望拥有自己的窗口,而不是立即显示它,不是吗?

步骤 5

关于 COleVariant 的注意事项:COleVariant 只是 VARIANT 类型的包装器 MFC 类。 另请注意,GetSynonymList() 方法返回一个 VARIANT,其中包含 BSTR 类型的安全数组。

第 6 步

添加文本到语音控件:这很简单。 这是一个 ActiveX 控件,可能已经安装在您的系统中。 如果没有,请尝试此链接。 从注册的 ActiveX 控件列表中添加文本到语音类。 像往常一样将其与按钮处理程序连接。 调用 Speak 方法,将所需的文本作为参数传递。

现在,我们将调用每个 Word 对象来重复在第 4 步中描述的后台进程。

使用代码

//
void CWordtestDlg::OnButton1() 
{
  // TODO: Add your control notification handler code here
  UpdateData();
  if(m_Word=="") 
  {
    m_Word="Type the word to search...";
    UpdateData(0);
    return;
   } 
   //(Edit box)
   // clear the curent synonym-list (Combo box)
   m_SynComb.ResetContent();

   COleVariant vTrue((short)TRUE), vFalse((short)FALSE),  
                      vOpt((long)DISP_E_PARAMNOTFOUND, VT_ERROR);
   
   //Start a new instance of Microsoft Word
   _Application oWordApp;
   if (!oWordApp.CreateDispatch("Word.Application", NULL))
   {
     AfxMessageBox("CreateDispatch failed.", MB_OK | MB_SETFOREGROUND);
     return;
   }

   Documents oDocs;
   _Document oDoc;
   oDocs = oWordApp.GetDocuments();
   //Add a doc
   oDoc = oDocs.Add(vOpt, vOpt,vOpt, vOpt);
   // create a Selection object
   Selection oSel;
   // get Selection
   oSel = oWordApp.GetSelection();
   // set text to the word-unknown...
   oSel.SetText(m_Word);
   // get the Range object
   Range oRng=oSel.GetRange();
   // get the SynonymInfo object
   SynonymInfo oSin=oRng.GetSynonymInfo(); 
   // let's find the synonym list for the first meaning only
   COleVariant vMeaning(short(1));
   //get it...
   COleVariant vSyno=oSin.GetSynonymList(vMeaning); 
   long index=0;
   //does nothing... just a confirmation
   if(vSyno.vt==(VT_ARRAY|VT_BSTR))
   {
     CString str;
     int syncount;
     // get the size of the list
     syncount=(vSyno.parray)->cbElements;
     long* ptr;
     HRESULT lResult;
     // no synonyms... but the server is the first to know this!!! 
     //and it will react
     if(syncount==0) return;
          // lock the safe-array before extraction
     lResult=SafeArrayLock(vSyno.parray);
     if(lResult)return;
    for(int i=0 ; i < syncount ; i++)
    {
           // get the pointer to the array data
       ptr=(long*) (vSyno.parray)->pvData;
       // get each meaning
       str=(BSTR)ptr[i];
       // add to the combo
       m_SynComb.AddString(str);
    }
        // done... so unlock
    lResult=SafeArrayUnlock(vSyno.parray);
        if (lResult) return;
   }
   m_SynList="It means...";//(Combo)
   UpdateData(FALSE);// display list
}

版本历史

  • 2002 年 12 月 18 日 - 初始版本
© . All rights reserved.