Microsoft KB Archive/316207

From BetaArchive Wiki

Article ID: 316207

Article Last Modified on 1/17/2007



APPLIES TO

  • Microsoft Visual C++ .NET 2002 Standard Edition
  • Microsoft Word 2000 Standard Edition
  • Microsoft Word 2002 Standard Edition
  • Microsoft Visual C++ .NET 2003 Standard Edition
  • Microsoft Office Word 2003



This article was previously published under Q316207


For a Microsoft Visual C++ 6.0 version of this article, see 238611.

IN THIS TASK

Note Microsoft Visual C++ .NET (2002) supports both the managed code model that is provided by the Microsoft .NET Framework and the unmanaged native Microsoft Windows code model. The information in this article applies only to unmanaged Visual C++ code.

SUMMARY

This step-by-step article describes how to embed a Word document in a View object in a single-document interface (SDI) Microsoft Foundation Classes (MFC) application by using Visual C++ .NET.

back to the top

Create an MFC Application that Embeds a Word Document

The following steps demonstrate how to embed a Word document and automate the document to add data to a cell.

  1. Start Microsoft Visual Studio .NET. On the File menu, click New, and then click Project. Under Project types click Visual C++ Projects, and then click MFC Application under Templates. Name the project Embed_Word.
  2. When the MFC Application Wizard appears, follow these steps:
    1. Click Application Type and then select Single Document.
    2. Click Compound Document Support and then select Container.
    3. Click Finish to accept all other default settings.
  3. Add interfaces from the Word object library. To do this, follow these steps:
    1. On the Project menu, click Add Class.
    2. Select MFC Class From TypeLib from the list of templates and click Open. The Add Class From TypeLib Wizard appears.
    3. In the list of available type libraries, locate Microsoft Word version Object Library. For Word 2000, the version is 9.0. For Word 2002, the version is 10.0. For Word 2003 the version is 11.
    4. Add the following interfaces:
      • _Document
      • Range
    5. Click Finish.
  4. Add the following line to Cntritem.h as a public member function of the CEmbed_WordCntrItem class:

    LPDISPATCH GetIDispatch();
  5. Add the GetIDispatch method to Cntritem.cpp, as follows:

    /*******************************************************************
    *   This method returns the IDispatch* for the application that is linked to
    *   this container.
    ********************************************************************/ 
    LPDISPATCH CEmbed_WordCntrItem::GetIDispatch()
    {
        //The this and m_lpObject pointers must be valid for this function
        //to work correctly. The m_lpObject is the IUnknown pointer to
        // this object.
        ASSERT_VALID(this);
    
        ASSERT(m_lpObject != NULL);
    
        LPUNKNOWN lpUnk = m_lpObject;
    
        //The embedded application must be running in order for the rest
        //of the function to work.
        Run();
    
        //QI for the IOleLink interface of m_lpObject.
        LPOLELINK lpOleLink = NULL;
        if (m_lpObject->QueryInterface(IID_IOleLink,
            (LPVOID FAR*)&lpOleLink) == NOERROR)
        {
            ASSERT(lpOleLink != NULL);
            lpUnk = NULL;
    
            //Retrieve the IUnknown interface to the linked application.
            if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
            {
                TRACE0("Warning: Link is not connected!\n");
                lpOleLink->Release();
                return NULL;
            }
            ASSERT(lpUnk != NULL);
        }
    
        //QI for the IDispatch interface of the linked application.
        LPDISPATCH lpDispatch = NULL;
        if (lpUnk->QueryInterface(IID_IDispatch, (LPVOID FAR*)&lpDispatch)
            !=NOERROR)
        {
            TRACE0("Warning: does not support IDispatch!\n");
            return NULL;
        }
    
        //After you verify that it is valid, return the IDispatch
        //interface to the caller.
        ASSERT(lpDispatch != NULL);
        return lpDispatch;
    }
                        
  6. Add the following line to Embed_wordview.h as a public method of the CEmbed_WordView class:

    void EmbedAutomateWord();
                        
  7. Add the following lines to Embed_wordview.cpp:

    #include "CDocument0.h"
    #include "CRange.h"
    
    /********************************************************************
    *   This method encapsulates the process of embedding an Word
    *   document in a View object and automating that document to add
    *   some text.
    ********************************************************************/ 
    void CEmbed_WordView::EmbedAutomateWord()
    {
       //Change the cursor so that the user knows that something exciting is going
       //on.
       BeginWaitCursor();
    
       CEmbed_WordCntrItem* pItem = NULL;
       TRY
       {
        //Get the document that is associated with this view, and be sure that it is
        //valid.
        CEmbed_WordDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
    
        //Create a new item associated with this document, and be sure that it is
        //valid.
        pItem = new CEmbed_WordCntrItem(pDoc);
        ASSERT_VALID(pItem);
    
        // Get the Class ID for the Word document.
        // This is used in creation.
        CLSID clsid;
        if(FAILED(::CLSIDFromProgID(L"Word.document",&clsid)))
            //Any exception will do. You just need to break out of the
            //TRY statement.
            AfxThrowMemoryException();
    
        // Create the Word embedded item.
        if(!pItem->CreateNewItem(clsid))
            //Any exception will do. You just need to break out of the
            //TRY statement.
            AfxThrowMemoryException();
    
        //Make sure that the new CContainerItem is valid.
        ASSERT_VALID(pItem);
    
        // Start the server to edit the item.
        pItem->DoVerb(OLEIVERB_SHOW, this);
    
        // As an arbitrary user interface design, this sets the
        // selection to the last item inserted.
        m_pSelection = pItem;   // Set selection to the last inserted item.
        pDoc->UpdateAllViews(NULL);
    
        //Query for the dispatch pointer for the embedded object. In
        //this case, this is the Word document.
        LPDISPATCH lpDisp;
        lpDisp = pItem->GetIDispatch();
    
        //Add text to the embedded Word document.
        CDocument0 wdDoc;
        CRange wdRange;
    
        //set CDocument0 wdDoc to use lpDisp, the IDispatch* of the
        //actual document.
        wdDoc.AttachDispatch(lpDisp);
    
    
        //Get a CRange object for the document.
        wdRange = wdDoc.Range(COleVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ),
             COleVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ) );
    
        //Fill the range with the string "Hello, World!"
        wdRange.put_Text( "Hello, World!" );
       }
    
       //Clean up if something went wrong.
       CATCH(CException, e)
       {
        if (pItem != NULL)
        {
            ASSERT_VALID(pItem);
             pItem->Delete();
        }
        AfxMessageBox(IDP_FAILED_TO_CREATE);
       }
       END_CATCH
    
        //Set the cursor back to normal so the user knows exciting stuff
        //is no longer happening.
        EndWaitCursor();
    }
                        
  8. Replace the code for CEmbed_WordView::OnInsertObject in Embed_wordview.cpp with the following:

    void CEmbed_WordView::OnInsertObject()
    {
        EmbedAutomateWord();
    }
                            

    NOTE: EmbedAutomateWord is merely a special case of OnInsertObject, which allows the user to select from a list of available OLE objects to insert into the application. You will override this behavior because it is not needed for this demonstration.

back to the top

Test the Application

  1. Press F5 to build and run the application.
  2. On the Edit menu of the application, click Insert New Object.
  3. Examine the results. A new Word document is embedded into the View object, with the text "Hello, World!".

back to the top

Troubleshooting

If you add class wrappers for the Word object library by using the File option in the Add Class From TypeLib Wizard, you may receive an error message when you browse to the object library. To avoid this problem, type the full path and file name for the object library instead of browsing to the file. For additional information, click the article number below to view the article in the Microsoft Knowledge Base:

311408 BUG: 'Read-Only' Warning When Adding MFC Class From Library


back to the top

REFERENCES

For more information, see the following Microsoft Developer Network (MSDN) Web site:

Microsoft Office Development with Visual Studio
http://msdn2.microsoft.com/en-us/library/aa188489(office.10).aspx


For additional information about Word Automation, see the following Knowledge Base articles:

308338 How To Automate Word To Perform a Mail Merge From C++ .NET and MFC


309294 How To Handle Events for Microsoft Word by Using C++ .NET and MFC


back to the top


Additional query words: ole object linking and embedding

Keywords: kbcontainer kbhowtomaster KB316207