Click here to Skip to main content
15,881,852 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.
#include "StdAfx.h"
#include "wfcontrolsite.h"
#include "WinFormsView.h"

//#using <mscorlib.dll>

#define S_QUICKACTIVATED S_FALSE

CWFControlSite::~CWFControlSite(void)
{
}

//***
//*** Override CreateControl so that we can call CreateManagedControl
//*** This is not an optimal solution because we are completely recoding
//*** CreateControl so that we can call CreateManagedControl rather than
//*** CreateOrLoad but CreateOrLoad is not virtual and so cannot be overridden
//***
HRESULT CWFControlSite::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
	LPCTSTR lpszWindowName, DWORD dwStyle, const POINT* ppt, const SIZE* psize,
   UINT nID, CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
{
	HRESULT hr = E_FAIL;
	m_hWnd = NULL;
    CSize size;

	// Connect the OLE Control with its proxy CWnd object
	if (pWndCtrl != NULL)
	{
        //***
		//*** NOTE: m_pCtrlSite is protected and so I can't access it
        //***
        //***  This is one of two changes to this method from the 
        //***  base class implementation
        //***
        // ASSERT(pWndCtrl->m_pCtrlSite == NULL);
		// m_pWndCtrl = pWndCtrl;
		// pWndCtrl->m_pCtrlSite = this;

		SetControlSite(pWndCtrl);
	}

	// Initialize OLE, if necessary
	_AFX_THREAD_STATE* pState = AfxGetThreadState();
	if (!pState->m_bNeedTerm && !AfxOleInit())
		return hr;

    //***
    //*** NOTE: Changed from CreateOrLoad to CreateManagedControl
    //***       This is one of two changes to this method from the 
    //***       base class implementation
    //***
	if (SUCCEEDED(hr = CreateManagedControl(clsid, pPersist, bStorage, bstrLicKey)))
	{
		ASSERT(m_pObject != NULL);
		m_nID = nID;

		if (psize == NULL)
		{
			// If psize is NULL, ask the object how big it wants to be.
			CClientDC dc(NULL);

			m_pObject->GetExtent(DVASPECT_CONTENT, &size);
			dc.HIMETRICtoDP(&size);
			m_rect = CRect(*ppt, size);
		}
		else
		{
			m_rect = CRect(*ppt, *psize);
		}

		m_dwStyleMask = WS_GROUP | WS_TABSTOP;

		if (m_dwMiscStatus & OLEMISC_ACTSLIKEBUTTON)
			m_dwStyleMask |= BS_DEFPUSHBUTTON;

		if (m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME)
			dwStyle &= ~WS_VISIBLE;

		m_dwStyle = dwStyle & m_dwStyleMask;

		// If control wasn't quick-activated, then connect sinks now.
		if (hr != S_QUICKACTIVATED)
		{
			m_dwEventSink = ConnectSink(m_iidEvents, &m_xEventSink);
			m_dwPropNotifySink = ConnectSink(IID_IPropertyNotifySink,
				&m_xPropertyNotifySink);
		}
		m_dwNotifyDBEvents = ConnectSink(IID_INotifyDBEvents, &m_xNotifyDBEvents);

		// Now that the object has been created, attempt to
		// in-place activate it.

		SetExtent();

		if (SUCCEEDED(hr = m_pObject->QueryInterface(IID_IOleInPlaceObject,
				(LPVOID*)&m_pInPlaceObject)))
		{
			if (dwStyle & WS_VISIBLE)
			{
				// control is visible: just activate it
				hr = DoVerb(OLEIVERB_INPLACEACTIVATE);
			}
			else
			{
				// control is not visible: activate off-screen, hide, then move
				m_rect.OffsetRect(-32000, -32000);
				if (SUCCEEDED(hr = DoVerb(OLEIVERB_INPLACEACTIVATE)) &&
					SUCCEEDED(hr = DoVerb(OLEIVERB_HIDE)))
				{
					m_rect.OffsetRect(32000, 32000);
					hr = m_pInPlaceObject->SetObjectRects(m_rect, m_rect);
				}
			}
		}
		else
		{
			TRACE(traceOle, 0, "IOleInPlaceObject not supported on OLE control (dialog ID %d).\n", nID);
			TRACE(traceOle, 0, ">>> Result code: 0x%08lx\n", hr);
		}

		if (SUCCEEDED(hr))
			GetControlInfo();

		// if QueryInterface or activation failed, cleanup everything
		if (FAILED(hr))
		{
			if (m_pInPlaceObject != NULL)
			{
				m_pInPlaceObject->Release();
				m_pInPlaceObject = NULL;
			}
			DisconnectSink(m_iidEvents, m_dwEventSink);
			DisconnectSink(IID_IPropertyNotifySink, m_dwPropNotifySink);
			DisconnectSink(IID_INotifyDBEvents, m_dwNotifyDBEvents);
			m_dwEventSink = 0;
			m_dwPropNotifySink = 0;
			m_dwNotifyDBEvents = 0;
			m_pObject->Release();
			m_pObject = NULL;
		}
	}

	if (SUCCEEDED(hr))
	{
		AttachWindow();

		// Initialize the control's Caption or Text property, if any
		if (lpszWindowName != NULL)
			SetWindowText(lpszWindowName);

		// Initialize styles
		ModifyStyle(0, m_dwStyle | (dwStyle & (WS_DISABLED|WS_BORDER)), 0);
	}

	return hr;
}

//***
//*** This method replaces CreateOrLoad for managed classes
//***
//*** clsid, pPersist, bStorage and bstrLicKey are ignored because we are using 
//*** managed to create the control. 
//***
//*** TODO: Make this work for licenses managed controls
//***
//*** This code is based on CreateorLoad
//***
//***
HRESULT CWFControlSite::CreateManagedControl( REFCLSID clsid
                                            , CFile* pPersist
                                            , BOOL bStorage
                                            , BSTR bstrLicKey)

{
	HRESULT hr = E_FAIL;
	ASSERT(m_pObject == NULL);

    //***
    //*** Downcast to CWFControlWrapper - have I used the right cast type?
    //*** And we should ASSERT on the type (boy is my C++ is out of date)
    //***
	//CUserCtrlView::CWFControlWrapper * pWndCtrlLocal = dynamic_cast<CUserCtrlView::CWFControlWrapper *>(m_pWndCtrl);
	CUserCtrlView::CWFControlWrapper * pWndCtrlLocal = (CUserCtrlView::CWFControlWrapper *)(m_pWndCtrl);

	IUnknown * pUnk = pWndCtrlLocal->GetManagedControl();
	
    if (FAILED(hr = pUnk->QueryInterface(IID_IOleObject, (void**)&m_pObject))) {
		return hr;
	}

	GetEventIID(&m_iidEvents);
	
    // Try to quick-activate first
	BOOL bQuickActivated = QuickActivate();

	if (!bQuickActivated)
	{
		m_pObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);

		// set client site first, if appropriate
		if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
		{
			if (FAILED(hr = m_pObject->SetClientSite(&m_xOleClientSite)))
			{
				goto CreateFailed;
			}
		}
	}

	if (!bQuickActivated)
	{
		// set client site last, if appropriate
		if (!(m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
		{
			if (FAILED(hr = m_pObject->SetClientSite(&m_xOleClientSite)))
			{
				goto CreateFailed;
			}
		}
	}

CreateFailed:
	if (FAILED(hr) && (m_pObject != NULL))
	{
		m_pObject->Close(OLECLOSE_NOSAVE);
		m_pObject->Release();
		m_pObject = NULL;
	}

	if (bQuickActivated && SUCCEEDED(hr))
		hr = S_QUICKACTIVATED;

	return hr;


}

//*** 
//*** m_pCtrlSite is protected and so I can't access it
//*** This method relies on new accessors on CWFControlWrapper
//*** 
void CWFControlSite::SetControlSite(CWnd* pWndCtrl) {

    //***
    //*** Downcast to CWFControlWrapper - have I used the right cast type?
    //*** And we should ASSERT on the type (boy is my C++ is out of date)
    //***
	//CUserCtrlView::CWFControlWrapper * pWndCtrlLocal = dynamic_cast<CUserCtrlView::CWFControlWrapper *>(pWndCtrl);
	CUserCtrlView::CWFControlWrapper * pWndCtrlLocal = (CUserCtrlView::CWFControlWrapper *)(pWndCtrl);

    //ASSERT(pWndCtrlLocal->GetControlSite() == NULL);
    m_pWndCtrl = pWndCtrlLocal;
    pWndCtrlLocal->SetControlSite(this);
}

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