从(非托管)C ++访问MS-Word拼写检查程序

时间:2010-01-28 10:41:37

标签: c++ com interop ms-word

我发现了一些关于与C#的MS-Word拼写检查器进行交互并使用.NET管理C​​ ++的文章。 (对于任何感兴趣的人:thisthis

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

1 个答案:

答案 0 :(得分:4)

我这样做了。 并不复杂。我把整个东西打包在一个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);
};

和实施(只有最重要的部分,对德国评论感到抱歉 - >如果需要,我会翻译它们)

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();
    }
}