| Tenouk C & C++ | MFC Home | OLE & Containers 7 | OLE & Containers 9 | Download | Site Index |


 

 

 

 

 

 

OLE Embedded Components and Containers part 8

 

 

 

 

 

 

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.

 

  1. The Coding Part

 

The Coding Part

 

Add the following code to ex32c.h.

 

friend class CEx32cDoc;

 

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

 

Listing 1.

 

Add the following code to the InitInstance() of ex32c.cpp.

 

TRACE("CEx32cApp::InitInstance\n");

 

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

 

Listing 2.

 

Edit the following code portion.

 

      // When a server application is launched stand-alone, it is a good idea

      //  to update the system registry in case it has been damaged.

      m_server.UpdateRegistry(OAT_SERVER);

      AfxMessageBox("Server can't be run stand-alone, use container -- Registry updated");

      return FALSE;

      //    // Dispatch commands specified on the command line

      //    if (!ProcessShellCommand(cmdInfo))

      //          return FALSE;

      //    // The one and only window has been initialized, so show and update it.

      //    m_pMainWnd->ShowWindow(SW_SHOW);

      //    m_pMainWnd->UpdateWindow();

      //    return TRUE;

 

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

 

Listing 3.

 

And the following code to the ExitInstance().

 

int CEx32cApp::ExitInstance()

{

      // TODO: Add your specialized code here and/or call the base class

      TRACE("CEx32cApp::ExitInstance\n");

      return CWinApp::ExitInstance();

}

 

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

 

Listing 4.

 

Edit the OnDraw() code of ex32cView.cpp.

 

void CEx32cView::OnDraw(CDC* pDC)

{

      CEx32cDoc* pDoc = GetDocument();

      ASSERT_VALID(pDoc);

      pDC->Rectangle(CRect(500, -1000, 1500, -2000));

      pDC->TextOut(5, 5, pDoc->m_strText);

}

 

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

 

Listing 5.

 

Edit the OnPrepareDC() as shown below.

 

void CEx32cView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)

{

      // TODO: Add your specialized code here and/or call the base class

      pDC->SetMapMode(MM_HIMETRIC);

}

 

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

 

Listing 6.

 

Add the following codes to ex32cDoc.h just after the preprocessor directives

 

extern const CLSID clsid; // defined in ex32c.cpp

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

 

#define SETFORMATETC(fe, cf, asp, td, med, li) \

      ((fe).cfFormat=cf, \

       (fe).dwAspect=asp, \

       (fe).ptd=td, \

       (fe).tymed=med, \

       (fe).lindex=li)

 

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

 

Listing 7.

 

Add the following friend class, then adds those member variables and member function.

 

friend class CEx32cView;

 

private:

      CString m_strText;

      LPOLECLIENTSITE m_lpClientSite;

      LPOLEADVISEHOLDER m_lpOleAdviseHolder;

      LPDATAADVISEHOLDER m_lpDataAdviseHolder;

      CString m_strContainerApp;

      CString m_strContainerObj;

 

      HGLOBAL MakeMetaFile();

 

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

 

Listing 8.

 

Manually add the following interface for IOleObject, IDataObject and IPersistStorage just after the previous codes.

 

BEGIN_INTERFACE_PART(OleObject, IOleObject)

            STDMETHOD(SetClientSite)(LPOLECLIENTSITE);

            STDMETHOD(GetClientSite)(LPOLECLIENTSITE*);

            STDMETHOD(SetHostNames)(LPCOLESTR, LPCOLESTR);

            STDMETHOD(Close)(DWORD);

            STDMETHOD(SetMoniker)(DWORD, LPMONIKER);

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

            STDMETHOD(InitFromData)(LPDATAOBJECT, BOOL, DWORD);

            STDMETHOD(GetClipboardData)(DWORD, LPDATAOBJECT*);

            STDMETHOD(DoVerb)(LONG, LPMSG, LPOLECLIENTSITE, LONG, HWND, LPCRECT);

            STDMETHOD(EnumVerbs)(LPENUMOLEVERB*);

            STDMETHOD(Update)();

            STDMETHOD(IsUpToDate)();

            STDMETHOD(GetUserClassID)(LPCLSID);

            STDMETHOD(GetUserType)(DWORD, LPOLESTR*);

            STDMETHOD(SetExtent)(DWORD, LPSIZEL);

            STDMETHOD(GetExtent)(DWORD, LPSIZEL);

            STDMETHOD(Advise)(LPADVISESINK, LPDWORD);

            STDMETHOD(Unadvise)(DWORD);

            STDMETHOD(EnumAdvise)(LPENUMSTATDATA*);

            STDMETHOD(GetMiscStatus)(DWORD, LPDWORD);

            STDMETHOD(SetColorScheme)(LPLOGPALETTE);

      END_INTERFACE_PART(OleObject)

 

      BEGIN_INTERFACE_PART(DataObject, IDataObject)

            STDMETHOD(GetData)(LPFORMATETC, LPSTGMEDIUM);

            STDMETHOD(GetDataHere)(LPFORMATETC, LPSTGMEDIUM);

            STDMETHOD(QueryGetData)(LPFORMATETC);

            STDMETHOD(GetCanonicalFormatEtc)(LPFORMATETC, LPFORMATETC);

            STDMETHOD(SetData)(LPFORMATETC, LPSTGMEDIUM, BOOL);

            STDMETHOD(EnumFormatEtc)(DWORD, LPENUMFORMATETC*);

            STDMETHOD(DAdvise)(LPFORMATETC, DWORD, LPADVISESINK, LPDWORD);

            STDMETHOD(DUnadvise)(DWORD);

            STDMETHOD(EnumDAdvise)(LPENUMSTATDATA*);

      END_INTERFACE_PART(DataObject)

 

      BEGIN_INTERFACE_PART(PersistStorage, IPersistStorage)

            STDMETHOD(GetClassID)(LPCLSID);

            STDMETHOD(IsDirty)();

            STDMETHOD(InitNew)(LPSTORAGE);

            STDMETHOD(Load)(LPSTORAGE);

            STDMETHOD(Save)(LPSTORAGE, BOOL);

            STDMETHOD(SaveCompleted)(LPSTORAGE);

            STDMETHOD(HandsOffStorage)();

      END_INTERFACE_PART(PersistStorage)

 

      DECLARE_INTERFACE_MAP()

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

 

Listing 9.

 

Delete (or comment out) the AppWizard generated DECLARE_DISPATCH_MAP and DECLARE_INTERFACE_MAP.

 

 

//    // Generated OLE dispatch map functions

//    //{{AFX_DISPATCH(CEx32cDoc)

//          // NOTE - the ClassWizard will add and remove member functions here.

//          //    DO NOT EDIT what you see in these blocks of generated code !

//    //}}AFX_DISPATCH

//    DECLARE_DISPATCH_MAP()

//    DECLARE_INTERFACE_MAP()

 

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

 

Listing 10.

 

Add the following #include directive to ex32cDoc.cpp.

 

#include "TextDialog.h"

 

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

 

Listing 11.

 

Manually add the following interface.

 

BEGIN_INTERFACE_MAP(CEx32cDoc, CDocument)

      INTERFACE_PART(CEx32cDoc, IID_IOleObject, OleObject)

      INTERFACE_PART(CEx32cDoc, IID_IDataObject, DataObject)

      INTERFACE_PART(CEx32cDoc, IID_IPersistStorage, PersistStorage)

END_INTERFACE_MAP()

 

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

 

Listing 12.

 

Delete (or comment out) the auto AppWizard generated DISPATCH_MAP and INTERFACE_MAP.

 

// BEGIN_DISPATCH_MAP(CEx32cDoc, CDocument)

//    //{{AFX_DISPATCH_MAP(CEx32cDoc)

//          // NOTE - the ClassWizard will add and remove mapping macros here.

//          //      DO NOT EDIT what you see in these blocks of generated code!

//    //}}AFX_DISPATCH_MAP

// END_DISPATCH_MAP()

 

// // Note: we add support for IID_IEx32c to support typesafe binding

// //  from VBA.  This IID must match the GUID that is attached to the

// //  dispinterface in the .ODL file.

 

// // {100A83A5-C1FB-4EA7-8AFC-689433F842E8}

// static const IID IID_IEx32c =

// { 0x100a83a5, 0xc1fb, 0x4ea7, { 0x8a, 0xfc, 0x68, 0x94, 0x33, 0xf8, 0x42, 0xe8 } };

 

// BEGIN_INTERFACE_MAP(CEx32cDoc, CDocument)

//    INTERFACE_PART(CEx32cDoc, IID_IEx32c, Dispatch)

// END_INTERFACE_MAP()

 

 

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

 

Listing 13.

 

Add the implementation for the interfaces. Firstly add the implementation for OleObject just after the previous commented codes.

 

///////////////////////////////////////////////////////////////////////

// CEx32cDoc OLE interface functions

STDMETHODIMP_(ULONG) CEx32cDoc::XOleObject::AddRef()

{

      TRACE("CEx32cDoc::XOleObject::AddRef\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      return pThis->InternalAddRef();

}

 

STDMETHODIMP_(ULONG) CEx32cDoc::XOleObject::Release()

{

      TRACE("CEx32cDoc::XOleObject::Release\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      return pThis->InternalRelease();

}

 

STDMETHODIMP CEx32cDoc::XOleObject::QueryInterface(REFIID iid, LPVOID* ppvObj)

{

      ITrace(iid, "CEx32cDoc::XOleObject::QueryInterface");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      return pThis->InternalQueryInterface(&iid, ppvObj);

}

 

STDMETHODIMP CEx32cDoc::XOleObject::SetClientSite(LPOLECLIENTSITE pClientSite)

{

      TRACE("CEx32cDoc::XOleObject::SetClientSite\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      // linked objects do not support SetClientSite

      if (pClientSite != NULL)

            pClientSite->AddRef();

      if(pThis->m_lpClientSite != NULL) pThis->m_lpClientSite->Release();

      pThis->m_lpClientSite = pClientSite;

 

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetClientSite(LPOLECLIENTSITE* ppClientSite)

{

      TRACE("CEx32cDoc::XOleObject::GetClientSite\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

 

      *ppClientSite = pThis->m_lpClientSite;

        if (pThis->m_lpClientSite != NULL)

                pThis->m_lpClientSite->AddRef();  // IMPORTANT

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::SetHostNames(LPCOLESTR szContainerApp, LPCOLESTR szContainerObj)

{

      TRACE("CEx32cDoc::XOleObject::SetHostNames\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

     

      CString strTitle = "EX28C object embedded in ";

      if(szContainerApp != NULL) {

            strTitle += CString(szContainerApp);

      }

      CWnd* pWnd = AfxGetMainWnd();

      pWnd->SetWindowText(strTitle);

 

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::Close(DWORD /*dwSaveOption*/)

{

      TRACE("CEx32cDoc::XOleObject::Close\n");

      // linked objects do not support close

 

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::SetMoniker(DWORD /*dwWhichMoniker*/, LPMONIKER /*pmk*/)

{

      TRACE("CEx32cDoc::XOleObject::SetMoniker\n");

      // linked objects do not support SetMoniker

 

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, LPMONIKER* ppMoniker)

{

      TRACE("CEx32cDoc::XOleObject::GetMoniker\n");

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::InitFromData(LPDATAOBJECT /*pDataObject*/, BOOL /*fCreation*/, DWORD/*dwReserved*/)

{

      TRACE("CEx32cDoc::XOleObject::InitFromData\n");

      // linked objects do not support InitFromData

 

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetClipboardData(DWORD /*dwReserved*/, LPDATAOBJECT* ppDataObject)

{

      TRACE("CEx32cDoc::XOleObject::GetClipboardData\n");

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::DoVerb(LONG iVerb, LPMSG lpmsg, LPOLECLIENTSITE pActiveSite, LONG lindex, HWND hwndParent, LPCRECT lpPosRect)

{

      TRACE("CEx32cDoc::XOleObject::DoVerb - %d\n", iVerb);

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

 

      pThis->InternalAddRef();    // protect this object

      CWnd* pWnd = AfxGetMainWnd();

      switch (iVerb)

      {

      // open - maps to OnOpen

      case OLEIVERB_OPEN:

      case -OLEIVERB_OPEN-1:  // allows positive OLEIVERB_OPEN-1 in registry

      case OLEIVERB_PRIMARY:  // OLEIVERB_PRIMARY is 0 and "Edit" in registry

      case OLEIVERB_SHOW:

            pWnd->ShowWindow(SW_SHOW);

            pWnd->SetActiveWindow();

            pWnd->SetForegroundWindow();

            break;

 

      // hide maps to OnHide

      case OLEIVERB_HIDE:

      case -OLEIVERB_HIDE-1:  // allows positive OLEIVERB_HIDE-1 in registry

            return E_NOTIMPL;

 

      default:

            // negative verbs not understood should return E_NOTIMPL

            if (iVerb < 0)

                  return E_NOTIMPL;

 

            AfxThrowOleException(OLEOBJ_S_INVALIDVERB);

      }

      pThis->InternalRelease();   // may 'delete this'

      pThis->m_lpClientSite->OnShowWindow(TRUE); // hatch

 

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::EnumVerbs(IEnumOLEVERB** ppenumOleVerb)

{

      TRACE("CEx32cDoc::XOleObject::EnumVerbs\n");

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::Update()

{

      TRACE("CEx32cDoc::XOleObject::Update\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::IsUpToDate()

{

      TRACE("CEx32cDoc::XOleObject::IsUpToDate\n");

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetUserClassID(CLSID* pClsid)

{

      TRACE("CEx32cDoc::XOleObject::GetUserClassID\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

 

      return pThis->m_xPersistStorage.GetClassID(pClsid);

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetUserType(DWORD dwFormOfType, LPOLESTR* ppszUserType)

{

      TRACE("CEx32cDoc::XOleObject::GetUserType\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

 

      *ppszUserType = NULL;

 

      CLSID clsid;

      pThis->m_xOleObject.GetUserClassID(&clsid);

      return OleRegGetUserType(clsid, dwFormOfType, ppszUserType);

}

 

STDMETHODIMP CEx32cDoc::XOleObject::SetExtent(DWORD /*dwDrawAspect*/, LPSIZEL /*lpsizel*/)

{

      TRACE("CEx32cDoc::XOleObject::SetExtent\n");

      return E_FAIL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)

{

      TRACE("CEx32cDoc::XOleObject::GetExtent\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

      // handler returns extent in metafilepict

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::Advise(IAdviseSink* pAdvSink, DWORD* pdwConnection)

{

      TRACE("CEx32cDoc::XOleObject::Advise\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

      *pdwConnection = 0;

      if (pThis->m_lpOleAdviseHolder == NULL &&

            ::CreateOleAdviseHolder(&pThis->m_lpOleAdviseHolder)

            != NOERROR) {

            return E_OUTOFMEMORY;

      }

      ASSERT(pThis->m_lpOleAdviseHolder != NULL);

      return pThis->m_lpOleAdviseHolder->Advise(pAdvSink, pdwConnection);

}

 

STDMETHODIMP CEx32cDoc::XOleObject::Unadvise(DWORD dwConnection)

{

      TRACE("CEx32cDoc::XOleObject::Unadvise\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::EnumAdvise(LPENUMSTATDATA* ppenumAdvise)

{

      TRACE("CEx32cDoc::XOleObject::EnumAdvise\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XOleObject::GetMiscStatus(DWORD dwAspect, DWORD* pdwStatus)

{

      TRACE("CEx32cDoc::XOleObject::GetMiscStatus\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

 

      *pdwStatus = 0;

 

      CLSID clsid;

      pThis->m_xOleObject.GetUserClassID(&clsid);

      return OleRegGetMiscStatus(clsid, dwAspect, pdwStatus);

}

 

STDMETHODIMP CEx32cDoc::XOleObject::SetColorScheme(LPLOGPALETTE lpLogpal)

{

      TRACE("CEx32cDoc::XOleObject::SetColorScheme\n");

      METHOD_PROLOGUE(CEx32cDoc, OleObject)

      ASSERT_VALID(pThis);

 

      return E_NOTIMPL;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Next, add the implementation codes for DataObject.

 

// CEx32cDoc::XDataObject

// delegate many calls to embedded COleDataSource object, which manages formats

STDMETHODIMP_(ULONG) CEx32cDoc::XDataObject::AddRef()

{

      TRACE("CEx32cDoc::XDataObject::AddRef\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      return pThis->InternalAddRef();

}

 

STDMETHODIMP_(ULONG) CEx32cDoc::XDataObject::Release()

{

      TRACE("CEx32cDoc::XDataObject::Release\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      return pThis->InternalRelease();

}

 

STDMETHODIMP CEx32cDoc::XDataObject::QueryInterface(REFIID iid, LPVOID* ppvObj)

{

      ITrace(iid, "CEx32cDoc::XDataObject::QueryInterface");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      return pThis->InternalQueryInterface(&iid, ppvObj);

}

 

STDMETHODIMP CEx32cDoc::XDataObject::GetData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)

{

      TRACE("CEx32cDoc::XDataObject::GetData -- %d\n", lpFormatEtc->cfFormat);

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

 

      if(lpFormatEtc->cfFormat != CF_METAFILEPICT) {

            return S_FALSE;

      }

      HGLOBAL hPict = pThis->MakeMetaFile();

      lpStgMedium->tymed = TYMED_MFPICT;

      lpStgMedium->hMetaFilePict = hPict;

      lpStgMedium->pUnkForRelease = NULL;

      return S_OK;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::GetDataHere(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium)

{

      TRACE("CEx32cDoc::XDataObject::GetDataHere\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::QueryGetData(LPFORMATETC lpFormatEtc)

{

      TRACE("CEx32cDoc::XDataObject::QueryGetData -- %d\n", lpFormatEtc->cfFormat);

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

      if(lpFormatEtc->cfFormat != CF_METAFILEPICT) {

            return S_FALSE;

      }

      return S_OK;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::GetCanonicalFormatEtc(LPFORMATETC /*lpFormatEtcIn*/, LPFORMATETC /*lpFormatEtcOut*/)

{

      TRACE("CEx32cDoc::XDataObject::GetCanonicalFormatEtc\n");

      return DATA_S_SAMEFORMATETC;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::SetData(LPFORMATETC lpFormatEtc, LPSTGMEDIUM lpStgMedium, BOOL bRelease)

{

      TRACE("CEx32cDoc::XDataObject::SetData\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC* ppenumFormatEtc)

{

      TRACE("CEx32cDoc::XDataObject::EnumFormatEtc\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::DAdvise(FORMATETC* pFormatEtc, DWORD advf, LPADVISESINK pAdvSink, DWORD* pdwConnection)

{

      TRACE("CEx32cDoc::XDataObject::DAdvise\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

 

      *pdwConnection = 555;

      // create the advise holder, if necessary

      if (pThis->m_lpDataAdviseHolder == NULL &&

            CreateDataAdviseHolder(&pThis->m_lpDataAdviseHolder) != S_OK) {

            return E_OUTOFMEMORY;

      }

      ASSERT(pThis->m_lpDataAdviseHolder != NULL);

      HRESULT hr = pThis->m_lpDataAdviseHolder->Advise(this, pFormatEtc, advf, pAdvSink, pdwConnection);

      return hr;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::DUnadvise(DWORD dwConnection)

{

      TRACE("CEx32cDoc::XDataObject::DUnadvise\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

 

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XDataObject::EnumDAdvise(LPENUMSTATDATA* ppenumAdvise)

{

      TRACE("CEx32cDoc::XDataObject::EnumDAdvise\n");

      METHOD_PROLOGUE(CEx32cDoc, DataObject)

      ASSERT_VALID(pThis);

 

      return E_NOTIMPL;

}

 

 

Finally for PersistStorage.

 

/////////////////////////////////////////////////////////////

// XPersistStorage

STDMETHODIMP_(ULONG) CEx32cDoc::XPersistStorage::AddRef()

{

      TRACE("CEx32cDoc::XPersistStorage:::AddRef\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      return pThis->InternalAddRef();

}

 

STDMETHODIMP_(ULONG) CEx32cDoc::XPersistStorage::Release()

{

      TRACE("CEx32cDoc::XPersistStorage::Release\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      return pThis->InternalRelease();

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::QueryInterface(REFIID iid, LPVOID* ppvObj)

{

      ITrace(iid, "CEx32cDoc::XPersistStorage::QueryInterface");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      return pThis->InternalQueryInterface(&iid, ppvObj);

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::GetClassID(LPCLSID lpClassID)

{

      TRACE("CEx32cDoc::XPersistStorage::GetClassID\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

      *lpClassID = clsid;

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::IsDirty()

{

      TRACE("CEx32cDoc::XPersistStorage::IsDirty\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

 

      return pThis->IsModified() ? NOERROR : S_FALSE;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::InitNew(LPSTORAGE pStg)

{

      TRACE("CEx32cDoc::XPersistStorage::InitNew\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

      ASSERT(pStg != NULL);

 

      pThis->SetModifiedFlag();  // new storage-based documents are dirty!

      pThis->SendInitialUpdate(); // in CDocument

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::Load(LPSTORAGE pStgLoad)

{

      TRACE("CEx32cDoc::XPersistStorage::Load\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

 

      ASSERT(pStgLoad != NULL);

      LPSTREAM pStream;

      ULONG nBytesRead;

      char buffer[101]; // 100 characters max for m_strText

      try {

            pThis->DeleteContents();

            if(pStgLoad->OpenStream(L"Ex28c Text", NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream) == NOERROR) {

                  pStream->Read(buffer, 100, &nBytesRead);

                  pStream->Release();

                  pThis->m_strText = buffer;

            }

      }

      catch(CException* pe) {

            pe->Delete();

            return E_FAIL;

      }

 

      pThis->SetModifiedFlag();  // new storage-based documents are dirty!

      pThis->SendInitialUpdate(); // in CDocument

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::Save(LPSTORAGE pStgSave, BOOL fSameAsLoad)

{

      TRACE("CEx32cDoc::XPersistStorage::Save\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

 

      // don't bother saving if destination is up-to-date

      if (fSameAsLoad && !pThis->IsModified())

            return NOERROR;

 

      ASSERT(pStgSave != NULL);

      LPSTREAM pStream;

      ULONG nBytesWritten;

      try   {

            if(pStgSave->CreateStream(L"Ex28c Text", STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,0, 0, &pStream) == NOERROR)

             {

                  pStream->Write((const char*) pThis->m_strText,

                              pThis->m_strText.GetLength() + 1, &nBytesWritten);

                  pStream->Release();

            }

            else return E_FAIL;

      }

      catch(CException* pe) {

            pe->Delete();

            return E_FAIL;

      }

 

      pThis->SetModifiedFlag();  // new storage-based documents are dirty!

      pThis->SendInitialUpdate(); // in CDocument

      return NOERROR;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::SaveCompleted(LPSTORAGE pStgSaved)

{

      TRACE("CEx32cDoc::XPersistStorage::SaveCompleted\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

 

      return E_NOTIMPL;

}

 

STDMETHODIMP CEx32cDoc::XPersistStorage::HandsOffStorage()

{

      TRACE("CEx32cDoc::XPersistStorage::HandsOffStorage\n");

      METHOD_PROLOGUE(CEx32cDoc, PersistStorage)

      ASSERT_VALID(pThis);

 

      return E_NOTIMPL;

}

 

Add and/or edit other codes starting from the constructor.

 

CEx32cDoc::CEx32cDoc()

{

      // TODO: add one-time construction code here

      TRACE("CEx32cDoc ctor\n");

      m_lpClientSite = NULL;

      m_lpOleAdviseHolder = NULL;

      m_lpDataAdviseHolder = NULL;

}

 

CEx32cDoc::~CEx32cDoc()

{

      TRACE("CEx32cDoc dtor\n");

}

 

BOOL CEx32cDoc::OnNewDocument()

{

      TRACE("CEx32cDoc::OnNewDocument\n");

      if (!CDocument::OnNewDocument())

            return FALSE;

      m_strText = "Default text";

      return TRUE;

}

 

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

 

Listing 14.

 

 

This function is manually added if you not using ClassView during the adding of the MakeMetaFile() declaration in ex32cDoc.h.

 

HGLOBAL CEx32cDoc::MakeMetaFile()

{

      HGLOBAL hPict;

      CMetaFileDC dcm;

      VERIFY(dcm.Create());

      CSize size(5000, 5000); // initial size of object in Excel & Word

      dcm.SetMapMode(MM_ANISOTROPIC);

      dcm.SetWindowOrg(0,0);

      dcm.SetWindowExt(size.cx, -size.cy);

      // drawing code

      dcm.Rectangle(CRect(500, -1000, 1500, -2000));

    CFont font;

    font.CreateFont(-500, 0, 0, 0, 400, FALSE, FALSE, 0,

                    ANSI_CHARSET, OUT_DEFAULT_PRECIS,

                    CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,

                    DEFAULT_PITCH | FF_SWISS, "Arial");

    CFont* pFont = dcm.SelectObject(&font);

      dcm.TextOut(0, 0, m_strText);

    dcm.SelectObject(pFont);

 

      HMETAFILE hMF = dcm.Close();

      ASSERT(hMF != NULL);

      hPict = ::GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, sizeof(METAFILEPICT));

      ASSERT(hPict != NULL);

      LPMETAFILEPICT lpPict;

      lpPict = (LPMETAFILEPICT) ::GlobalLock(hPict);

      ASSERT(lpPict != NULL);

      lpPict->mm = MM_ANISOTROPIC;

      lpPict->hMF = hMF;

      lpPict->xExt = size.cx;

      lpPict->yExt = size.cy;  // HIMETRIC height

      ::GlobalUnlock(hPict);

      return hPict;

}

 

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

 

Listing 15.

 

Add the following global diagnostic jus after the Dump().

 

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

 

Listing 16.

 

Edit the OnCloseDocument().

 

void CEx32cDoc::OnCloseDocument()

{

    // TODO: Add your specialized code here and/or call the base class

    InternalAddRef();

 

    if(m_lpClientSite != NULL) {

        m_lpClientSite->OnShowWindow(FALSE); // no hatch

        m_lpClientSite->Release();

    }

 

    if (m_lpOleAdviseHolder != NULL)

    // you need to send a close notification

        m_lpOleAdviseHolder->SendOnClose();

    // finish closing the document (before m_lpClientSite->Release)

    BOOL bAutoDelete = m_bAutoDelete;

    m_bAutoDelete = FALSE;

    CDocument::OnCloseDocument();

 

    // disconnect the object

    LPUNKNOWN lpUnknown = (LPUNKNOWN)GetInterface(&IID_IUnknown);

    ASSERT(lpUnknown != NULL);

    // this is very important to close circular references

    CoDisconnectObject(lpUnknown, 0);

 

    if(m_lpOleAdviseHolder != NULL)

        m_lpOleAdviseHolder->Release();

    if(m_lpDataAdviseHolder != NULL)

        m_lpDataAdviseHolder->Release();

 

    m_lpClientSite = NULL;

    m_lpOleAdviseHolder = NULL;

    m_lpDataAdviseHolder = NULL;

    // remove InternalAddRef above

    InterlockedDecrement(&m_dwRef);

    if (bAutoDelete) {

        delete this;

      }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

 

Listing 17.

 

Add/edit other codes.

 

void CEx32cDoc::OnModify()

{

      // TODO: Add your command handler code here

      CTextDialog dlg;

      dlg.m_strText = m_strText;

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

            m_strText = dlg.m_strText;

            UpdateAllViews(NULL); // redraw view

            // Notify the client that the metafile has changed.

            //  Client must call IViewObject::SetAdvise.

            LPDATAOBJECT lpDataObject = (LPDATAOBJECT) GetInterface(&IID_IDataObject);

            HRESULT hr =  m_lpDataAdviseHolder->SendOnDataChange(lpDataObject, 0, NULL);

            ASSERT(hr == NOERROR);

            SetModifiedFlag(); // won't update without this

      }

}

 

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

 

Listing 18.

 

void CEx32cDoc::OnFinalRelease()

{

      // TODO: Add your specialized code here and/or call the base class

      TRACE("CEx32cDoc::OnFinalRelease\n"); // so we can see it happen

      CDocument::OnFinalRelease();

}

 

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

 

Listing 19.

 

BOOL CEx32cDoc::SaveModified()

{

      // TODO: Add your specialized code here and/or call the base class

      OnFileUpdate();

      return TRUE;

}

 

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

 

Listing 20.

 

void CEx32cDoc::OnFileUpdate()

{

      // TODO: Add your command handler code here

      if(m_lpClientSite == NULL) return;

      VERIFY(m_lpClientSite->SaveObject() == NOERROR);

      if (m_lpOleAdviseHolder != NULL)

            m_lpOleAdviseHolder->SendOnSave();

      SetModifiedFlag(FALSE);

}

 

void CEx32cDoc::OnUpdateFileUpdate(CCmdUI* pCmdUI)

{

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

      pCmdUI->Enable(IsModified());

}

 

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

 

Listing 21.

 

Add the following #include directive in StdAfx.h.

 

#include <afxole.h>        // MFC OLE classes

 

And delete (or comment out) the following #include directives.

 

#include <afxdisp.h>

#include <afxdtctl.h>

 

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

 

Listing 22.

 

Finally, just delete the ODL file (ex32c.odl) or leave it empty as shown below. Select the file and use the Edit Delete menu.

 

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

 

Listing 23.

 

 

 

 

 

 

Further reading and digging:

  1. DCOM at MSDN.

  2. COM+ at MSDN.

  3. COM at MSDN.

  4. Win32 process, thread and synchronization story can be found starting from Module R.

  5. MSDN MFC 7.0 class library online documentation.

  6. MSDN MFC 9.0 class library online documentation - latest version.

  7. MSDN Library

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | OLE & Containers 7 | OLE & Containers 9 | Download | Site Index |