// Text.cpp : implementation file // implements IDispatch and IPersistStream // #include "stdafx.h" #include "ex27b.h" #include "Text.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CText IMPLEMENT_DYNCREATE(CText, CCmdTarget) CText::CText() { EnableAutomation(); // To keep the application running as long as an OLE automation // object is active, the constructor calls AfxOleLockApp. AfxOleLockApp(); m_pchText = NULL; } CText::~CText() { // To terminate the application when all objects created with // with OLE automation, the destructor calls AfxOleUnlockApp. if(m_pchText != NULL) { delete [] m_pchText; } AfxOleUnlockApp(); } void CText::OnFinalRelease() { // When the last reference for an automation object is released, // OnFinalRelease is called. The base class will automatically // delete the object. Add additional cleanup required for your // object before calling the base class. CCmdTarget::OnFinalRelease(); } BEGIN_MESSAGE_MAP(CText, CCmdTarget) //{{AFX_MSG_MAP(CText) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() BEGIN_DISPATCH_MAP(CText, CCmdTarget) //{{AFX_DISPATCH_MAP(CText) DISP_PROPERTY_EX(CText, "Text", GetText, SetText, VT_VARIANT) //}}AFX_DISPATCH_MAP END_DISPATCH_MAP() // Note: we add support for IID_IText to support typesafe binding // from VBA. This IID must match the GUID that is attached to the // dispinterface in the .ODL file. // {4EBFDD71-5F7D-11D0-848F-00400526305B} static const IID IID_IText = { 0x4ebfdd71, 0x5f7d, 0x11d0, { 0x84, 0x8f, 0x0, 0x40, 0x5, 0x26, 0x30, 0x5b } }; BEGIN_INTERFACE_MAP(CText, CCmdTarget) INTERFACE_PART(CText, IID_IPersistStream, PersistStream) INTERFACE_PART(CText, IID_IText, Dispatch) END_INTERFACE_MAP() // {4EBFDD72-5F7D-11D0-848F-00400526305B} IMPLEMENT_OLECREATE(CText, "ex26b.Text", 0x4ebfdd72, 0x5f7d, 0x11d0, 0x84, 0x8f, 0x0, 0x40, 0x5, 0x26, 0x30, 0x5b) ///////////////////////////////////////////////////////////////////////////// // CText message handlers VARIANT CText::GetText() { return COleVariant(m_pchText).Detach(); } void CText::SetText(const VARIANT FAR& newValue) { CString strTemp; ASSERT(newValue.vt == VT_BSTR); if(m_pchText != NULL) { delete [] m_pchText; } strTemp = newValue.bstrVal; // converts to narrow chars m_pchText = new char[strTemp.GetLength() + 1]; strcpy(m_pchText, strTemp); } ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP_(ULONG) CText::XPersistStream::AddRef() { METHOD_PROLOGUE(CText, PersistStream) return (ULONG) pThis->ExternalAddRef(); } STDMETHODIMP_(ULONG) CText::XPersistStream::Release() { METHOD_PROLOGUE(CText, PersistStream) return (ULONG) pThis->ExternalRelease(); } STDMETHODIMP CText::XPersistStream::QueryInterface(REFIID iid, void FAR* FAR* ppvObj) { METHOD_PROLOGUE(CText, PersistStream) // ExternalQueryInterface looks up iid in the macro-generated tables return (HRESULT) pThis->ExternalQueryInterface(&iid, ppvObj); } ///////////////////////////////////////////////////////////////////////////// STDMETHODIMP CText::XPersistStream::GetClassID(LPCLSID lpClassID) { TRACE("Entering CText::XPersistStream::GetClassID\n"); METHOD_PROLOGUE(CText, PersistStream) ASSERT_VALID(pThis); *lpClassID = CText::guid; return NOERROR; } STDMETHODIMP CText::XPersistStream::IsDirty() { TRACE("Entering CText::XPersistStream::IsDirty\n"); METHOD_PROLOGUE(CText, PersistStream) ASSERT_VALID(pThis); return NOERROR; } STDMETHODIMP CText::XPersistStream::Load(LPSTREAM pStm) { ULONG nLength; STATSTG statstg; METHOD_PROLOGUE(CText, PersistStream) ASSERT_VALID(pThis); if(pThis->m_pchText != NULL) { delete [] pThis->m_pchText; } // don't need to free statstg.pwcsName because of NONAME flag VERIFY(pStm->Stat(&statstg, STATFLAG_NONAME) == NOERROR); int nSize = statstg.cbSize.LowPart; // assume < 4 GB if(nSize > 0) { pThis->m_pchText = new char[nSize]; pStm->Read(pThis->m_pchText, nSize, &nLength); } return NOERROR; } STDMETHODIMP CText::XPersistStream::Save(LPSTREAM pStm, BOOL fClearDirty) { METHOD_PROLOGUE(CText, PersistStream) ASSERT_VALID(pThis); int nSize = strlen(pThis->m_pchText) + 1; pStm->Write(pThis->m_pchText, nSize, NULL); return NOERROR; } STDMETHODIMP CText::XPersistStream::GetSizeMax(ULARGE_INTEGER FAR* pcbSize) { TRACE("Entering CText::XPersistStream::GetSizeMax\n"); METHOD_PROLOGUE(CText, PersistStream) ASSERT_VALID(pThis); pcbSize->LowPart = strlen(pThis->m_pchText) + 1; pcbSize->HighPart = 0; // assume < 4 GB return NOERROR; }