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






4.40/5 (11投票s)
2002年12月18日
3分钟阅读

152509

3586
基于 MFC 的 MS Word 拼写检查器实现。
引言
每当我想知道一个单词的意思时,我通常会打开一个 Word 文档并搜索同义词。 所以,我想只调用词库,而不打开 Word 文档,那就太好了。 甚至让我的电脑发音这个单词就更好了。 自动化是第一个问题的答案,而 Microsoft 文本到语音控件解决了第二个问题。 我认为,来自 VC 的 Office 自动化是最缺乏文档的主题之一。 但是我们获得了大量的 VBA 文档。 让我们看看我是怎么做的。 我将向您展示一个循序渐进的方法。
步骤 1
打开一个基于 MFC 对话框的应用程序。
第二步
创建如图所示的控件。
步骤 3
打开类向导。 在“自动化”选项卡中,单击“添加类”-->“从类型库”。 打开文件对话框会要求提供“*.olb”文件。 您可以在“Microsoft Office 目录”中找到它。 对于 Office 2000,它是msword9.olb。 对于旧版本,它是msword8.olb。 如果找不到它,请搜索它! 但是您应该找到它,否则我们无法继续!!! 找到类型库后,打开它,会弹出一个新窗口。 它要求我们选择 Word 公开的自动化对象。 对于我们的目的,我们可能不需要所有这些。 因此,如果您不确定要选择哪些类,请选择所有类,然后按“确定”。
您可以看到正在将 2 个文件添加到项目中 - Msword9.cpp 和 Msword9.h(在旧版本中,它是 Msword8.cpp 和 Msword8.h)。 检查添加的新类。
正是 _Application
对象创建了 Word 应用程序实例。 Documents
类枚举文档,而 Document
类用于处理特定文档。
步骤 4
我希望您知道 Word 自动化需要哪些对象。 (如果您愿意,可以跳过此步骤。)如果您不确定,可以通过使用 Word 宏来获得一个不错的想法。 看一看... 打开一个新的 Word 文档。 选择工具--->宏--->录制新宏。 将宏存储在新文档本身中。 新的按钮集将被添加到工具栏,并且鼠标指针上会附加一个盒式磁带。 现在输入一些单词并选择它。(如果鼠标不太友好,请使用 shift+箭头键。) 选择工具--->语言--->词库。 现在,词库会显示同义词。 选择“替换”或“取消”。 在工具栏中,您可以看到宏的“停止”按钮。 停止它。 现在,如果您打开工具--->宏--->宏,您可以看到宏列表。 选择 Macro1(或您命名的任何名称),然后单击“编辑”。 它将在 VB 环境中打开。 您可以看到 Selection
对象被频繁使用。 词库窗口也正在从 Selection
的 Range
对象中被调用。 在您的应用程序中,如果您从 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 日 - 初始版本