| Tenouk | Home | Previous | Next | Download  |  Site Index  |  Disclaimer  |  Privacy | Contact | Tell friends |


 

 

OLE Embedded Components and Containers part 4

 

Program examples compiled using Visual C++ 6.0 compiler on Windows XP Pro machine with Service Pack 2. The Excel version is Excel 2003/Office 11. Topics and sub topics for this tutorial are listed below. Don’t forget to read Tenouk’s small disclaimer. The supplementary notes for this tutorial are IOleObject and OLE.

 

Index:
 
The EX32B From Scratch...continue

 

 

 

Add the #include directive in ex32bView.cpp.

 

#include <afxole.h>

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 7.

 

Modify the constructor as shown below.

 

CEx28bView::CEx28bView(): m_sizeTotal(20000, 25000),

    // 20 x 25 cm when printed

      m_rectTracker(0, 0, 0, 0)

{

      m_cfObjDesc = ::RegisterClipboardFormat(CF_OBJECTDESCRIPTOR);

      m_cfEmbedded = ::RegisterClipboardFormat(CF_EMBEDDEDOBJECT);

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 8.

 

Modify the OnDraw() as shown below.

 

void CEx32bView::OnDraw(CDC* pDC)

{

      CEx32bDoc* pDoc = GetDocument();

 

      if(pDoc->m_lpOleObj != NULL)

      {

            VERIFY(::OleDraw(pDoc->m_lpOleObj, DVASPECT_CONTENT,

                        pDC->GetSafeHdc(), m_rectTracker) == S_OK);

      }

   

      m_tracker.m_rect = m_rectTracker;

      pDC->LPtoDP(m_tracker.m_rect);   // device

      if(pDoc->m_bHatch)

      {

            m_tracker.m_nStyle |= CRectTracker::hatchInside;

      }

      else

      {

            m_tracker.m_nStyle &= ~CRectTracker::hatchInside;

      }

      m_tracker.Draw(pDC);

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 9.

 

Edit OnPreparePrinting() as shown below.

 

BOOL CEx32bView::OnPreparePrinting(CPrintInfo* pInfo)

{

      pInfo->SetMaxPage(1);

      return DoPreparePrinting(pInfo);

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 10.

 

Edit OnInitialUpdate() as shown below.

 

void CEx32bView::OnInitialUpdate()

{

      TRACE("CEx32bView::OnInitialUpdate\n");

      m_rectTracker = CRect(1000, -1000, 5000, -5000);

      m_tracker.m_nStyle = CRectTracker::solidLine |

            CRectTracker::resizeOutside;

      SetScrollSizes(MM_HIMETRIC, m_sizeTotal);

      CScrollView::OnInitialUpdate();

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 11.

 

Edit other message handlers as shown in the following codes.

 

void CEx32bView::OnEditCopy()

{

      // TODO: Add your command handler code here

      COleDataSource* pSource = SaveObject();

      if(pSource)

    {

      pSource->SetClipboard(); // OLE deletes data source

    }

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 12.

 

void CEx32bView::OnUpdateEditCopy(CCmdUI* pCmdUI)

{

      // TODO: Add your command update UI handler code here

      // serves Copy, Cut, and Copy To

    pCmdUI->Enable(GetDocument()->m_lpOleObj != NULL);

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 13.

 

void CEx32bView::OnEditCopyto()

{

    // TODO: Add your command handler code here

    // Copy text to an .STG file (nothing special about STG ext)

    CFileDialog dlg(FALSE, "stg", "*.stg");

    if (dlg.DoModal() != IDOK) {

        return;

    }

      CEx32bDoc* pDoc = GetDocument();

      // Create a structured storage home for the object (m_pStgSub).

      // Create a root storage file, then a substorage named "sub."

      LPSTORAGE pStgRoot;

      VERIFY(::StgCreateDocfile(dlg.GetPathName().AllocSysString(),

               STGM_READWRITE|STGM_SHARE_EXCLUSIVE|STGM_CREATE,

               0, &pStgRoot) == S_OK);

      ASSERT(pStgRoot != NULL);

     

      LPSTORAGE pStgSub;

      VERIFY(pStgRoot->CreateStorage(CEx32bDoc::s_szSub,

         STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE,

         0, 0, &pStgSub) == S_OK);

      ASSERT(pStgSub != NULL);

 

      // Get the IPersistStorage* for the object

      LPPERSISTSTORAGE pPS = NULL;

      VERIFY(pDoc->m_lpOleObj->QueryInterface(IID_IPersistStorage,

              (void**) &pPS) == S_OK);

      // Finally, save the object in its new home in the user's file

 

      VERIFY(::OleSave(pPS, pStgSub, FALSE) == S_OK);

      // FALSE means different stg

      pPS->SaveCompleted(NULL);  // What does this do?

      pPS->Release();

 

      pStgSub->Release();

      pStgRoot->Release();

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 14.

 

void CEx32bView::OnEditCut()

{

    // TODO: Add your command handler code here

    OnEditCopy();

    GetDocument()->OnEditClearAll();

}

 

 

Listing 15.

 

void CEx32bView::OnEditInsertobject()

{

      // TODO: Add your command handler code here

      CEx32bDoc* pDoc = GetDocument();

      COleInsertDialog dlg;

      if(dlg.DoModal() == IDCANCEL) return;

      // no addrefs done for GetInterface

      LPOLECLIENTSITE pClientSite = (LPOLECLIENTSITE)pDoc->GetInterface(&IID_IOleClientSite);

      ASSERT(pClientSite != NULL);

      pDoc->DeleteContents();

      VERIFY(::OleCreate(dlg.GetClassID(), IID_IOleObject,

               OLERENDER_DRAW, NULL, pClientSite, pDoc->m_pTempStgSub,

      (void**) &pDoc->m_lpOleObj) == S_OK);

      SetViewAdvise();

 

      pDoc->m_lpOleObj->DoVerb(OLEIVERB_SHOW, NULL, pClientSite, 0,

            NULL, NULL); // OleRun doesn't show it

      SetNames();

      GetDocument()->SetModifiedFlag();

      GetSize();

      pDoc->UpdateAllViews(NULL);

}

 

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 16.

 

void CEx32bView::OnUpdateEditInsertobject(CCmdUI* pCmdUI)

{

      // TODO: Add your command update UI handler code here

      pCmdUI->Enable(GetDocument()->m_lpOleObj == NULL);

}

 

void CEx32bView::OnEditPaste()

{

      // TODO: Add your command handler code here

      CEx32bDoc* pDoc = GetDocument();

      COleDataObject dataObject;

      VERIFY(dataObject.AttachClipboard());

      pDoc->DeleteContents();

      DoPasteObjectDescriptor(&dataObject);

      DoPasteObject(&dataObject);

      SetViewAdvise();

      GetSize();

      pDoc->SetModifiedFlag();

      pDoc->UpdateAllViews(NULL);

}

 

void CEx32bView::OnUpdateEditPaste(CCmdUI* pCmdUI)

{

      // TODO: Add your command update UI handler code here

      // Make sure that object data is available

      COleDataObject dataObject;

      if (dataObject.AttachClipboard() && dataObject.IsDataAvailable(m_cfEmbedded))

       { pCmdUI->Enable(TRUE); }

    else

    { pCmdUI->Enable(FALSE); }

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 17.

 

void CEx32bView::OnEditPastefrom()

{

    // TODO: Add your command handler code here

    CEx32bDoc* pDoc = GetDocument();

    // Paste from an .STG file

    CFileDialog dlg(TRUE, "stg", "*.stg");

    if (dlg.DoModal() != IDOK)

    { return; }

    // Open the storage and substorage

      LPSTORAGE pStgRoot;

      VERIFY(::StgOpenStorage(dlg.GetPathName().AllocSysString(), NULL,

               STGM_READ|STGM_SHARE_EXCLUSIVE,

               NULL, 0, &pStgRoot) == S_OK);

      ASSERT(pStgRoot != NULL);

     

      LPSTORAGE pStgSub;

      VERIFY(pStgRoot->OpenStorage(CEx32bDoc::s_szSub, NULL,

               STGM_READ|STGM_SHARE_EXCLUSIVE,

               NULL, 0, &pStgSub) == S_OK);

      ASSERT(pStgSub != NULL);

 

      // Copy the object data from the user storage to the temporary storage

      VERIFY(pStgSub->CopyTo(NULL, NULL, NULL,

               pDoc->m_pTempStgSub) == S_OK);

      // Finally, load the object -- pClientSite not necessary

      LPOLECLIENTSITE pClientSite =

            (LPOLECLIENTSITE) pDoc->GetInterface(&IID_IOleClientSite);

      ASSERT(pClientSite != NULL);

      pDoc->DeleteContents();

      VERIFY(::OleLoad(pDoc->m_pTempStgSub, IID_IOleObject, pClientSite,

              (void**) &pDoc->m_lpOleObj) == S_OK);

      SetViewAdvise();

      pStgSub->Release();

      pStgRoot->Release();

      GetSize();

    pDoc->SetModifiedFlag();

    pDoc->UpdateAllViews(NULL);

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

 

Listing 18.

 

void CEx32bView::OnLButtonDblClk(UINT nFlags, CPoint point)

{

    // TODO: Add your message handler code here and/or call default

    if(m_tracker.HitTest(point) == CRectTracker::hitNothing) return;

    // Activate the object

    CEx32bDoc* pDoc = GetDocument();

    if(pDoc->m_lpOleObj != NULL)

    {

      LPOLECLIENTSITE pClientSite =

            (LPOLECLIENTSITE) pDoc->GetInterface(&IID_IOleClientSite);

      ASSERT(pClientSite != NULL);

      VERIFY(pDoc->m_lpOleObj->DoVerb(OLEIVERB_OPEN, NULL, pClientSite, 0,

                  GetSafeHwnd(), CRect(0, 0, 0, 0)) == S_OK);

      SetNames();

      GetDocument()->SetModifiedFlag();

    }

}

 

void CEx32bView::OnLButtonDown(UINT nFlags, CPoint point)

{

      // TODO: Add your message handler code here and/or call default

      TRACE("**Entering CEx32bView::OnLButtonDown -- point = (%d, %d)\n",

             point.x, point.y);

       if(m_tracker.Track(this, point, FALSE, NULL))

       {

            CClientDC dc(this);

            OnPrepareDC(&dc);

            m_rectTracker = m_tracker.m_rect;

            dc.DPtoLP(m_rectTracker); // Update logical coords

            GetDocument()->UpdateAllViews(NULL);

      }

      TRACE("**Leaving CEx32bView::OnLButtonDown\n");

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 19.

 

BOOL CEx32bView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)

{

      // TODO: Add your message handler code here and/or call default

      if(m_tracker.SetCursor(pWnd, nHitTest))

      {

            return TRUE;

      }

      else

      {

            return CScrollView::OnSetCursor(pWnd, nHitTest, message);

      }

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 20.

 

Complete other message handlers’ codes previously added.

 

void CEx32bView::GetSize()

{

      CEx32bDoc* pDoc = GetDocument();

      if(pDoc->m_lpOleObj != NULL)

      {

            SIZEL size;   // Ask the component for its size

            pDoc->m_lpOleObj->GetExtent(DVASPECT_CONTENT, &size);

            m_rectTracker.right = m_rectTracker.left + size.cx;

            m_rectTracker.bottom = m_rectTracker.top - size.cy;

      }

}

 

void CEx32bView::SetNames()

{

      CEx32bDoc* pDoc = GetDocument();

      CString strApp = AfxGetApp()->m_pszAppName;

      if(pDoc->m_lpOleObj != NULL)

      { pDoc->m_lpOleObj->SetHostNames(strApp.AllocSysString(), NULL); }

}

 

void CEx32bView::SetViewAdvise()

{

      CEx32bDoc* pDoc = GetDocument();

      if(pDoc->m_lpOleObj != NULL)

      {

            LPVIEWOBJECT2 pViewObj;

            pDoc->m_lpOleObj->QueryInterface(IID_IViewObject2,

                  (void**) &pViewObj);

            LPADVISESINK pAdviseSink =

                  (LPADVISESINK) pDoc->GetInterface(&IID_IAdviseSink);

            VERIFY(pViewObj->SetAdvise(DVASPECT_CONTENT, 0, pAdviseSink)

                  == S_OK);

            pViewObj->Release();

      }

}

 

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 21.

 

BOOL CEx32bView::MakeMetafilePict(COleDataSource *pSource)

{

      CEx32bDoc* pDoc = GetDocument();

      COleDataObject dataObject;

      LPDATAOBJECT pDataObj; // OLE object's IDataObject interface

      VERIFY(pDoc->m_lpOleObj->QueryInterface(IID_IDataObject,

              (void**) &pDataObj) == S_OK);

      dataObject.Attach(pDataObj);

    FORMATETC fmtem;

    SETFORMATETC(fmtem, CF_METAFILEPICT, DVASPECT_CONTENT, NULL,

        TYMED_MFPICT, -1);

    if (!dataObject.IsDataAvailable(CF_METAFILEPICT, &fmtem))

    {

      TRACE("CF_METAFILEPICT format is unavailable\n");

      return FALSE;

    }

      // Just copy the metafile handle from the OLE object

      //  to the clipboard data object

      STGMEDIUM stgmm;

      VERIFY(dataObject.GetData(CF_METAFILEPICT, &stgmm, &fmtem));

      pSource->CacheData(CF_METAFILEPICT, &stgmm, &fmtem);

      return TRUE;

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 22.

 

COleDataSource* CEx32bView::SaveObject()

{

      TRACE("Entering CEx32bView::SaveObject\n");

      CEx32bDoc* pDoc = GetDocument();

       if (pDoc->m_lpOleObj != NULL)

       {

        COleDataSource* pSource = new COleDataSource();

        // CODE FOR OBJECT DATA

        FORMATETC fmte;

        SETFORMATETC(fmte, m_cfEmbedded, DVASPECT_CONTENT, NULL,

            TYMED_ISTORAGE, -1);

        STGMEDIUM stgm;

        stgm.tymed = TYMED_ISTORAGE;

        stgm.pstg = pDoc->m_pTempStgSub;

        stgm.pUnkForRelease = NULL;

            pDoc->m_pTempStgSub->AddRef();   // must do both!

            pDoc->m_pTempStgRoot->AddRef();

            pSource->CacheData(m_cfEmbedded, &stgm, &fmte);

            // metafile needed too

            MakeMetafilePict(pSource);

            // CODE FOR OBJECT DESCRIPTION DATA

            HGLOBAL hObjDesc = ::GlobalAlloc(GMEM_SHARE, sizeof(OBJECTDESCRIPTOR));

            LPOBJECTDESCRIPTOR pObjDesc =

                (LPOBJECTDESCRIPTOR) ::GlobalLock(hObjDesc);

            pObjDesc->cbSize = sizeof(OBJECTDESCRIPTOR);

            pObjDesc->clsid = CLSID_NULL;

            pObjDesc->dwDrawAspect = 0;

            pObjDesc->dwStatus = 0;

            pObjDesc->dwFullUserTypeName = 0;

            pObjDesc->dwSrcOfCopy = 0;

            pObjDesc->sizel.cx = 0;

            pObjDesc->sizel.cy = 0;

            pObjDesc->pointl.x = 0;

            pObjDesc->pointl.y = 0;

            ::GlobalUnlock(hObjDesc);

            pSource->CacheGlobalData(m_cfObjDesc, hObjDesc);

            return pSource;

      }

      return NULL;

}

 

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 23.

 

BOOL CEx32bView::DoPasteObject(COleDataObject *pDataObject)

{

    TRACE("Entering CEx32bView::DoPasteObject\n");

    // Update command UI should keep us out of here if not

    //  CF_EMBEDDEDOBJECT

    if (!pDataObject->IsDataAvailable(m_cfEmbedded))

    {

      TRACE("CF_EMBEDDEDOBJECT format is unavailable\n");

      return FALSE;

    }

      CEx32bDoc* pDoc = GetDocument();

      // Now create the object from the IDataObject*.

      //  OleCreateFromData will use CF_EMBEDDEDOBJECT format if available.

      LPOLECLIENTSITE pClientSite =

                  (LPOLECLIENTSITE) pDoc->GetInterface(&IID_IOleClientSite);

      ASSERT(pClientSite != NULL);

      VERIFY(::OleCreateFromData(pDataObject->m_lpDataObject,

               IID_IOleObject,OLERENDER_DRAW, NULL, pClientSite,

               pDoc->m_pTempStgSub, (void**) &pDoc->m_lpOleObj) == S_OK);

      return TRUE;

}

 

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 24.

 

BOOL CEx32bView::DoPasteObjectDescriptor(COleDataObject *pDataObject)

{

      TRACE("Entering CEx32bView::DoPasteObjectDescriptor\n");

      STGMEDIUM stg;

      FORMATETC fmt;

      CEx32bDoc* pDoc = GetDocument();

    if (!pDataObject->IsDataAvailable(m_cfObjDesc))

    {

      TRACE("OBJECTDESCRIPTOR format is unavailable\n");

      return FALSE;

    }

      SETFORMATETC(fmt, m_cfObjDesc, DVASPECT_CONTENT, NULL,

            TYMED_HGLOBAL, -1);

      VERIFY(pDataObject->GetData(m_cfObjDesc, &stg, &fmt));

     

      return TRUE;

}

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 25.

 

Add the following prototype in ex32bDoc.h.

 

void ITrace(REFIID iid, const char* str);

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 26.

 

Manually add the following interface OleClientSite and AdviseSink.

 

BEGIN_INTERFACE_PART(OleClientSite, IOleClientSite)

            STDMETHOD(SaveObject)();

            STDMETHOD(GetMoniker)(DWORD, DWORD, LPMONIKER*);

            STDMETHOD(GetContainer)(LPOLECONTAINER*);

            STDMETHOD(ShowObject)();

            STDMETHOD(OnShowWindow)(BOOL);

            STDMETHOD(RequestNewObjectLayout)();

      END_INTERFACE_PART(OleClientSite)

 

      BEGIN_INTERFACE_PART(AdviseSink, IAdviseSink)

            STDMETHOD_(void,OnDataChange)(LPFORMATETC, LPSTGMEDIUM);

            STDMETHOD_(void,OnViewChange)(DWORD, LONG);

            STDMETHOD_(void,OnRename)(LPMONIKER);

            STDMETHOD_(void,OnSave)();

            STDMETHOD_(void,OnClose)();

      END_INTERFACE_PART(AdviseSink)

 

      DECLARE_INTERFACE_MAP()

 

OLE Embedded Components and Containers - MFC C++ code snippet

 

Listing 27.

 

Add the following friend class (in order to access the private variables and member functions).

 

friend class CEx32bView;

 

private:

      LPOLEOBJECT m_lpOleObj;

      LPSTORAGE m_pTempStgRoot;

      LPSTORAGE m_pTempStgSub;

      BOOL m_bHatch;