Click here to Skip to main content
15,881,757 members
Articles / Desktop Programming / MFC

Develop MFC Doc/View Application Which Supports Any Number Document Template

Rate me:
Please Sign up or sign in to vote.
1.57/5 (3 votes)
2 Jun 20052 min read 36.5K   1.7K   26  
This article provides an introduction to TangramLittle, a C++ Framework for MFC and the .NET Framework. Knowledge in MFC and the .NET Framework is assumed.
// TangramLittle Library - version 1.0
// Author:      Sunhui
// Modified by:
// Created:     2005-04-06
// Copyright:   (c) Sunhui
// Licence:     wxWindows licence
//
// This source code is a part of Tangram library.
// The use and distribution terms for this software are covered by the
// The wxWindows Library Licence (http://opensource.org/licenses/wxwindows.php)
// which can be found in the file licence.txt at the root of this distribution.
// By using this software in any fashion, you are agreeing to be bound by
// the terms of this license. You must not remove this notice, or
// any other, from this software.

// XDocument.cpp : implementation file
//

#include "stdafx.h"
#include "dotnetextimpl.h"
#include "XDocument.h"
/*#include "TangramCntrItem.h"

BEGIN_INTERFACE_MAP(CAXDocContFrameHook, COleFrameHook)
  INTERFACE_PART(CAXDocContFrameHook, IID_IOleCommandTarget, OleCommandTarget)
END_INTERFACE_MAP()


STDMETHODIMP_(ULONG) CAXDocContFrameHook::XOleCommandTarget::AddRef()
{
	METHOD_PROLOGUE_EX_(CAXDocContFrameHook, OleCommandTarget)

	ULONG nResult = (ULONG)pThis->ExternalAddRef();

	return nResult;
}

STDMETHODIMP_(ULONG) CAXDocContFrameHook::XOleCommandTarget::Release()
{
	METHOD_PROLOGUE_EX_(CAXDocContFrameHook, OleCommandTarget)

	ULONG nResult = (ULONG)pThis->ExternalRelease();

	return nResult;
}

STDMETHODIMP CAXDocContFrameHook::XOleCommandTarget::QueryInterface(
	REFIID iid, LPVOID* ppvObj)
{
	METHOD_PROLOGUE_EX_(CAXDocContFrameHook, OleCommandTarget)

	HRESULT hr = (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);

	return hr;
}

/*
 * IOleCommandTarget methods, provided to make PowerPoint happy
 * with this frame.
 */

/*STDMETHODIMP CAXDocContFrameHook::XOleCommandTarget::QueryStatus(  const GUID* pguidCmdGroup, ULONG cCmds, OLECMD rgCmds[],
   OLECMDTEXT* pcmdtext)
{
	METHOD_PROLOGUE_EX_(CAXDocContFrameHook, OleCommandTarget)

	HRESULT	hr=NOERROR;

	COleCmdUI state(rgCmds, cCmds, pguidCmdGroup);
	if (pcmdtext == NULL)
		state.m_nCmdTextFlag = 0;
	else
		state.m_nCmdTextFlag = pcmdtext->cmdtextf;
				
	for (state.m_nIndex = 0; state.m_nIndex < cCmds; state.m_nIndex++)
	{
		state.m_nID = rgCmds[state.m_nIndex].cmdID;
		state.DoUpdate(g_pDotNetExtImpl->m_pCurDoc->m_pFrame->GetParentFrame(), TRUE);
	}
				
	if (pcmdtext != NULL && pcmdtext->rgwz != NULL &&
		(pcmdtext->cmdtextf != OLECMDTEXTF_NONE))
	{
		USES_CONVERSION;
		ASSERT(cCmds == 1);
		state.m_strText = state.m_strText.Right(pcmdtext->cwBuf-1);
		pcmdtext->cwActual = state.m_strText.GetLength();
					
#ifdef _UNICODE
		lstrcpyW(pcmdtext->rgwz, (LPCTSTR) state.m_strText);
#elif defined(OLE2ANSI)
		lstrcpy(pcmdtext->rgwz, state.m_strText);
#else
		lstrcpyW(pcmdtext->rgwz, T2W((LPCTSTR) state.m_strText));
#endif
	}

	return hr;
}

        
STDMETHODIMP CAXDocContFrameHook::XOleCommandTarget::Exec(const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt,
   VARIANTARG* pvarargIn, VARIANTARG* pvarargOut)
{
	METHOD_PROLOGUE_EX_(CAXDocContFrameHook, OleCommandTarget);

	HRESULT		hr=NOERROR;
	OLECMD		cmd;

	COleCmdUI	state(&cmd, 1, pguidCmdGroup);

	state.m_nIndex = 0;
	cmd.cmdf = 0;
	cmd.cmdID = nCmdID;
	state.m_nID = nCmdID;

	// help via Doc Object targeting is not supported

	if (nCmdExecOpt == OLECMDEXECOPT_SHOWHELP)
		hr = OLECMDERR_E_DISABLED;
	else
	{
		// is the command supported?

		if (!state.DoUpdate(g_pDotNetExtImpl->m_pCurDoc->m_pFrame->GetParentFrame(), TRUE))
			hr = OLECMDERR_E_NOTSUPPORTED;
		else
		{
			if (cmd.cmdf & OLECMDF_ENABLED)
			{
				if (g_pDotNetExtImpl->m_pCurDoc->m_pFrame->GetParentFrame()->OnCmdMsg(state.m_nID, CN_COMMAND, NULL, NULL))
					hr = S_OK;
				else
					hr = E_FAIL;
			}
			else
				hr = OLECMDERR_E_DISABLED;
		}
	}
	
	return hr;
}

BOOL CAXDocContFrameHook::OnDocActivate(BOOL bActive)
{
	ASSERT_VALID(this);
	if (m_lpActiveObject == NULL)
		return TRUE;

	// allow server to do document activation related actions
	m_lpActiveObject->OnDocWindowActivate(bActive);

	// make sure window caption gets updated later
	COleFrameHook* pNotifyHook = m_pActiveItem->m_pInPlaceFrame;
	if(pNotifyHook==NULL)return TRUE;
	pNotifyHook->m_pFrameWnd->DelayUpdateFrameTitle();

	if (!bActive)
	{
		// clear border space
		pNotifyHook->m_xOleInPlaceFrame.SetBorderSpace(NULL);
		if (m_pActiveItem->m_pInPlaceDoc != NULL)
			m_pActiveItem->m_pInPlaceDoc->m_xOleInPlaceFrame.SetBorderSpace(NULL);

		// remove the menu hook when the doc is not active
		pNotifyHook->m_xOleInPlaceFrame.SetMenu(NULL, NULL, NULL);

		// unhook top-level frame if not needed
		if (pNotifyHook != this)pNotifyHook->m_pFrameWnd->m_pNotifyHook = NULL;
	}
	else
		pNotifyHook->m_pFrameWnd->m_pNotifyHook = pNotifyHook;

	// don't do default if activating
	return bActive;
}
*/
// CXDocument

IMPLEMENT_DYNCREATE(CXDocument, COleDocument)

CXDocument::CXDocument()
{
	EnableCompoundFile(TRUE);
	g_pDotNetExtImpl->m_nDocCount++;
	m_nVbaObjID = -1;
	m_bMainDoc = false;
	m_bVBAPrj = false;
	m_pVbaConnector = NULL;
	m_pFrame = NULL;
	if(g_pDotNetExtImpl)
	{
		g_pDotNetExtImpl->m_pCurDoc = this;
		//Support VBA:
		if(g_pDotNetExtImpl->m_pVbaProjectRuntimeClass)
		{
			m_pVbaConnector = (CVbaProjectConnector*)g_pDotNetExtImpl->m_pVbaProjectRuntimeClass->CreateObject();
			m_pVbaConnector->m_pDoc=this;
		}
	}
}

BOOL CXDocument::OnNewDocument()
{
	if (!COleDocument::OnNewDocument())
		return FALSE;
		//Support VBA:
	if(m_pVbaConnector)
	{
		BOOL bRet=false;
		bRet = m_pVbaConnector->OnNewDocument();
		m_pVbaConnector->SetupReference();
		
		return bRet;
	}
    SetModifiedFlag(FALSE);
    UpdateAllViews(NULL);
	return TRUE;
}

CXDocument::~CXDocument()
{
	//Support VBA:
	if(m_pVbaConnector)
		delete m_pVbaConnector;
}


BEGIN_MESSAGE_MAP(CXDocument, COleDocument)
END_MESSAGE_MAP()

void CXDocument::LoadFromStorage()
{
	if(m_pVbaConnector)
		m_pVbaConnector->LoadFromStorage();
	else
		COleDocument::LoadFromStorage();
}

void CXDocument::SaveToStorage(CObject* pObject)
{
	if(m_pVbaConnector)
		m_pVbaConnector->SaveToStorage(pObject);
	else
		COleDocument::SaveToStorage(pObject);
}

IStorage* CXDocument::GetStorage()
{
	return m_lpRootStg;
}

BOOL CXDocument::GetRemember()
{
	return m_bRemember;
}

BOOL CXDocument::GetSaveState()
{
	return m_bSameAsLoad;
}
// CXDocument diagnostics

#ifdef _DEBUG
void CXDocument::AssertValid() const
{
	COleDocument::AssertValid();
}

void CXDocument::Dump(CDumpContext& dc) const
{
	COleDocument::Dump(dc);
}
#endif //_DEBUG


// CXDocument serialization

void CXDocument::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
		ar << m_nVbaObjID;
	}
	else
	{
		// TODO: add loading code here
		ar >> m_nVbaObjID;
	}
	COleDocument::Serialize(ar);
}


// CXDocument commands

IDispatch* CXDocument::GetDocDisp(void)
{
	return NULL;
}

void CXDocument::OnExternalCommand(LPCTSTR command, LPCTSTR args)
{
	TRACE(_T("Call CXDocument OnExternalCommand: %s, %s\r\n"),command,args);

	// TODO: Add your message handler code here
}

BOOL CXDocument::OnOpenDocument(LPCTSTR lpszPathName)
{
	if (!COleDocument::OnOpenDocument(lpszPathName))
		return FALSE;
	if(m_pVbaConnector)
	{
		m_pVbaConnector->m_pDoc->m_bVBAPrj = true;
		m_pVbaConnector->SetupReference();
	}

	// TODO:  Add your specialized creation code here

	return TRUE;
}

BOOL CXDocument::OnSaveDocument(LPCTSTR lpszPathName)
{
	USES_CONVERSION;

	if(!m_bMainDoc)
	{
		if (!COleDocument::OnSaveDocument(lpszPathName))
			return FALSE;
	}
	else
	{
		// use helper to save to root storage
		LPSTORAGE lpOrigStg = NULL;

		BOOL bResult = FALSE;
		// open new root storage if necessary
		m_bSameAsLoad=false;
		if (lpszPathName != NULL && !m_bSameAsLoad)
		{
			// temporarily detach current storage|STGM_SHARE_DENY_WRITE
			lpOrigStg = m_lpRootStg;
			m_lpRootStg = NULL;

			LPSTORAGE lpStorage;
			SCODE sc = ::StgCreateDocfile(T2COLE(lpszPathName),
				STGM_READWRITE|STGM_TRANSACTED|STGM_CREATE,
				0, &lpStorage);
			if (sc != S_OK)
				AfxThrowOleException(sc);

			ASSERT(lpStorage != NULL);
			m_lpRootStg = lpStorage;
			lpOrigStg->CopyTo(0,NULL,NULL,m_lpRootStg);
			sc = m_lpRootStg->Commit(STGC_DEFAULT);
			if (sc != S_OK)
				AfxThrowOleException(sc);
		}

		ASSERT(m_lpRootStg != NULL);

		// create Contents stream
		COleStreamFile file;
		CFileException fe;
		if (!file.CreateStream(m_lpRootStg, _T("Contents"),
				CFile::modeReadWrite|CFile::shareExclusive|CFile::modeCreate, &fe))
		{
			if (fe.m_cause == CFileException::fileNotFound)
				AfxThrowArchiveException(CArchiveException::badSchema);
			else
				AfxThrowFileException(fe.m_cause, fe.m_lOsError);
		}

		// save to Contents stream
		CArchive saveArchive(&file, CArchive::store | CArchive::bNoFlushOnDelete);
		saveArchive.m_pDocument = this;
		saveArchive.m_bForceFlat = FALSE;
		BOOL fNeedSaveCompleted = FALSE;

		TRY
		{
			if(m_pVbaConnector)
				fNeedSaveCompleted=m_pVbaConnector->SaveMainDoc(&saveArchive,true);
			else
			{
				// save the contents
				Serialize(saveArchive);
			}
			saveArchive.Close();
			file.Close();

			// commit the root storage
			SCODE sc = m_lpRootStg->Commit(STGC_DEFAULT);
			if (sc != S_OK)
				AfxThrowOleException(sc);
		}
		CATCH_ALL(e)
		{
			if(m_pVbaConnector&&fNeedSaveCompleted)
				m_pVbaConnector->SaveMainDoc(&saveArchive,false);

			file.Abort();   // will not throw an exception
			CommitItems(FALSE); // abort save in progress
			//NO_CPP_EXCEPTION(saveArchive.Abort());
			THROW_LAST();
		}
		END_CATCH_ALL
		if (lpszPathName != NULL)
		{
			// commit each of the items
			CommitItems(m_bRemember && !m_bSameAsLoad);

			// mark document as clean if remembering the storage
			if (m_bRemember)
				SetModifiedFlag(FALSE);

			// remember correct storage or release save copy as storage
			if (!m_bSameAsLoad)
			{
				if (m_bRemember)
				{
					// Save As case -- m_stgRoot is new storage, forget old storage
					lpOrigStg->Release();
				}
				else
				{
					// Save Copy As case -- m_stgRoot should hook up to m_stgOrig.
					m_lpRootStg->Release();
					m_lpRootStg = lpOrigStg;
				}
			}
		}
	}
	SetModifiedFlag(FALSE);
	return TRUE;
}

void CXDocument::DeleteContents()
{
	//Support VBA :
	if(m_pVbaConnector)
		m_pVbaConnector->Close();

	COleDocument::DeleteContents();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here



Comments and Discussions