【问题标题】:Access MS-Word spell-checker from (unmanaged) C++从(非托管)C++ 访问 MS-Word 拼写检查器
【发布时间】:2011-01-10 08:43:22
【问题描述】:

我发现了几篇关于从 C# 与 MS-Word 拼写检查器交互并使用 .NET 管理 C++ 的文章。 (任何有兴趣的人:thisthis

但我找不到任何可与使用 COM 在 MFC 应用程序中通过标准非托管 C++ 执行此操作的可比性。我假设 .NET 示例实际上使用了 COM,这意味着它是可能的,但是这样做会很可怕和丑陋吗?

【问题讨论】:

    标签: c++ com interop ms-word


    【解决方案1】:

    我做到了。 并不复杂。我将整个内容打包在一个 DLL 中,并自己制作了建议对话框。

    基本上它只是打开单词并要求它对特定的单个单词进行拼写检查。如果检查失败,请寻求建议。

    只有两点你会失败: 1. 一个文件必须是打开的,这意味着你总是必须在代码中创建一个 2. 对于不同的单词版本,字典有时存储为 unicode,有时(旧版本)不存储。当然,这仅在您想将新词存储到用户词典中时才重要。

    好的,代码如下:

    头文件:

    #pragma once
    #include "msword.h"
    
    class CWord  
    {
    public:
        CWord();
        bool Initialize();
        void Terminate();
        bool CheckSpelling(CString text);
        bool CorrectSpelling(CString text,CString& corrected,CWnd* pParent,CPoint point);
    
    private:
        _Application m_word;
        COleVariant m_vTrue;
        COleVariant m_vFalse;
        COleVariant m_vOpt;
        bool m_bInit;
    
        void AddToDictionary(CString text);
        CString OleErrorMsg(COleDispatchException* e);
    };
    

    以及实现(只有最重要的部分,对德国 cmets 感到抱歉 -> 如果需要,我会翻译它们)

    CWord::CWord()
    {
        // häufig gebrauchte Variants
        m_vFalse = COleVariant((short) FALSE);
        m_vTrue  = COleVariant((short) TRUE);
        m_vOpt   = COleVariant((long)DISP_E_PARAMNOTFOUND,VT_ERROR);
    
        m_bInit = false;
    }
    
    // sinnvolle Fehlermeldung erstellen
    CString CWord::OleErrorMsg(COleDispatchException* e)
    {
        CString msg;
    
        if(!e->m_strSource.IsEmpty())
            msg = e->m_strSource + " - ";
    
        if(!e->m_strDescription.IsEmpty())
            msg += e->m_strDescription;
        else
            msg += "Unbekannter Fehler.";
    
        return msg;
    }
    
    // Word starten
    bool CWord::Initialize()
    {
        try
        {
            if(!m_bInit)
            {
                m_word.CreateDispatch("Word.Application");
                m_bInit = true;
            }
        }
        catch(COleDispatchException* e) 
        {   
            AfxMessageBox(OleErrorMsg(e),MB_ICONEXCLAMATION);
            e->Delete();
            return false;
        }
    
        return true;
    }
    
    // Aufräumen
    void CWord::Terminate()
    {   
        try
        {   
            if(m_word != NULL)  
            {
                m_word.Quit(m_vFalse,m_vOpt,m_vOpt);
                m_word.DetachDispatch();
                m_word = NULL;
                m_bInit = false;
            }
        }
        catch(COleDispatchException* e)
        {
            AfxMessageBox(OleErrorMsg(e),MB_ICONEXCLAMATION);
            e->Delete();
        }
    }
    
    // ein Wort auf Rechtschreibung überprüfen
    bool CWord::CheckSpelling(CString text)
    {
        try
        {
            if(m_word == NULL)
            {
                AfxMessageBox("Word nicht initialisiert!",MB_ICONINFORMATION);
                return false;
            }
    
            int res = m_word.CheckSpelling((LPCTSTR) text,m_vOpt,m_vFalse,m_vOpt,
                m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt);
            return res != 0;
        }
        catch(COleDispatchException* e)
        {
            AfxMessageBox(OleErrorMsg(e),MB_ICONEXCLAMATION);
            e->Delete();
        }
    
        return false;
    }
    
    // Dialog mit Möglichkeiten anzeigen und Auswahl zurückgeben
    bool CWord::CorrectSpelling(CString text,CString& corrected,CWnd* pParent,CPoint /*point*/)
    {
        AFX_MANAGE_STATE(AfxGetStaticModuleState());
        ASSERT(pParent != NULL);
        bool ret = false;
    
        CVorschlagDlg dlg(pParent);
        dlg.m_strWort = text;
    
        try
        {
            // ein Dokument muss geöffnet sein, sonst verweigert GetSpellingSuggestions!
            Documents docs = m_word.GetDocuments();
            _Document doc = docs.Add(m_vOpt,m_vOpt,m_vOpt,m_vTrue);
    
            // jetzt die Vorschläge holen
            SpellingSuggestions spells = m_word.GetSpellingSuggestions((LPCTSTR) text,m_vOpt,m_vOpt,m_vOpt,
                m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt,m_vOpt);
    
            // in die Stringlist des Dialogs einfüllen
            for(int i = 1;i <= spells.GetCount();i++)
            {
                SpellingSuggestion ss = spells.Item(i);
                dlg.m_slVorschlaege.AddTail((LPCTSTR) ss.GetName());
            }
    
            // das Dokument wieder schliessen
            doc.SetSaved(TRUE);
            doc.Close(m_vFalse,m_vOpt,m_vOpt);
        }
        catch(COleDispatchException* e)
        {
            AfxMessageBox(OleErrorMsg(e),MB_ICONEXCLAMATION);
            e->Delete();
            return false;
        } 
    
        // Dialog öffnen und Ergebnis auswerten
        // ACHTUNG: im Switch fällt das Ergebnis durch bis zu 3 Cases durch!
        switch(dlg.DoModal())
        {
        case IDOK:
            // noch zum Word-Wörterbuch hinzufügen
            AddToDictionary(dlg.m_strWort);
    
        case IDYES:
        case IDIGNORE:
            corrected = dlg.m_strWort;
            ret = true;
            break;
    
        default: 
            break;
        } // switch
    
        return ret;
    } 
    
    void CWord::AddToDictionary(CString text)
    {
        CString strFilename;
        CStdioFile datei;
    
        try
        {
            // den Dateinamen herausfinden
            Dictionaries dics = m_word.GetCustomDictionaries();
            Dictionary dic = dics.GetActiveCustomDictionary();
            strFilename = dic.GetPath() + "\\" + dic.GetName();
        }
        catch(COleDispatchException* e)
        {
            AfxMessageBox(OleErrorMsg(e),MB_ICONEXCLAMATION);
            e->Delete();
            return;
        }
    
        try
        {
            if(!datei.Open(strFilename, CFile::modeReadWrite))
            {
                AfxMessageBox("Fehler beim Öffnen des Wörterbuches!",MB_ICONEXCLAMATION);
                return;
            }
    
            // herausfinden ob Datei UNICODE - kodiert - für Office 2007
            bool bUnicode = false;
            unsigned char cBOM[2];
            const unsigned char UNICODE_BOM[2] = {unsigned char(0xFF),unsigned char(0xFE)};
    
            if(datei.GetLength() > 2)
            {
                datei.Read((LPVOID) cBOM,2);
                bUnicode = cBOM[0] == UNICODE_BOM[0] &&  cBOM[1] == UNICODE_BOM[1];
            }
    
            datei.SeekToEnd();
    
            if(bUnicode)
            {
                USES_CONVERSION;
                LPCWSTR lpsz = T2W(text);
                datei.Write(lpsz,wcslen(lpsz) * sizeof(WCHAR)); 
            }
            else
            {
                datei.WriteString(text + "\n");
            }
    
            datei.Close();
    
    
            // jetzt noch das CRLF im Unicode nachschreiben
            if(bUnicode)
            {
                using namespace std;
                char crlf[4] = {13,0,10,0};
                //ofstream of(strFilename,ios_base::binary | ios_base::_Openmode::app);
                ofstream of(strFilename,ios_base::binary | ios_base::app);
                of.write(crlf,4);
                of.close();         
            }
        }
        catch(CException* e)
        {
            e->ReportError();
            e->Delete();
        }
    }
    

    【讨论】:

    • 如果你有任何我相信它会造福其他人和我。
    猜你喜欢
    • 2010-09-14
    • 2011-02-15
    • 1970-01-01
    • 2010-10-05
    • 1970-01-01
    • 2010-09-23
    • 2011-03-26
    • 2011-05-31
    • 2011-07-08
    相关资源
    最近更新 更多