Click here to Skip to main content
15,891,253 members
Articles / Desktop Programming / ATL

Host Silverlight Control in C++ using ATL

Rate me:
Please Sign up or sign in to vote.
4.82/5 (20 votes)
18 May 2010CPOL2 min read 173.9K   1.4K   38  
Hosting Silverlight control in C++ using ATL
// XcpControlHost.cpp : Implementation of CXcpControlHost

#include "stdafx.h"
#include "XcpControlHost.h"
#include "Ocidl.h"
#include "AtlProject_i.h"

#include "atlstr.h"

class CXcpPropertyBag:IPropertyBag
{
public:
	CXcpPropertyBag(){m_nRef=0;}
	~CXcpPropertyBag(){}

	HRESULT _stdcall QueryInterface(REFIID iid, void** ppvObject)
	{
		return S_OK;
	}

	ULONG _stdcall AddRef()
	{
		return ++m_nRef;
	}
	
	ULONG _stdcall Release()
	{
		if(--m_nRef == 0)
			delete this;

		return m_nRef;
	}

	ULONG m_nRef;

	STDMETHOD (Read)(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
	{
		HRESULT hr = E_INVALIDARG;
		BSTR bstrValue = NULL;
	  
		if (_wcsicmp(pszPropName, L"Source") == 0) 
		{
			bstrValue = SysAllocString(L"SilverlightTestApp.xap");
		}    
		else if (_wcsicmp(pszPropName, L"Background") == 0) 
		{
			bstrValue = SysAllocString(L"Gold");
		}

		else if (_wcsicmp(pszPropName, L"Windowless") == 0) 
		{
			V_VT(pVar) = VT_BOOL;
			V_BOOL(pVar) = VARIANT_FALSE;
			hr = S_OK;
		}

		if (bstrValue != NULL) 
		{
			V_VT(pVar) = VT_BSTR;
			V_BSTR(pVar) = bstrValue;
			hr = S_OK;
		}
		return hr;
	}

	
	STDMETHOD (Write)(LPCOLESTR pszPropName, VARIANT *pVar)
	{
		return S_OK;
	}
};


// CXcpControlHost

#pragma warning(disable:4061)

#include "stdafx.h"

#include "XcpControlHost.h"
#include "AtlProject_i.h"

 HWND CXcpControlHost::hControlWindow = NULL;
 IUnknown* CXcpControlHost::pUnKnown = NULL;
 XcpControlLib::IXcpControl2* CXcpControlHost::pControl = NULL;



///////////////////////////////////////////////////////////////////////////////
// CXcpControlHost IXcpControlHost Implementation

STDMETHODIMP CXcpControlHost::GetHostOptions(DWORD* pdwOptions)
{
	*pdwOptions = XcpHostOption_EnableCrossDomainDownloads|
		XcpHostOption_EnableScriptableObjectAccess|XcpHostOption_EnableHtmlDomAccess;
    return S_OK;
}

STDMETHODIMP CXcpControlHost::GetCustomAppDomain(IUnknown** ppAppDomain) 
{  
    return S_OK;
}

STDMETHODIMP CXcpControlHost::GetControlVersion(UINT *puMajorVersion, UINT *puMinorVersion)
{
	*puMajorVersion = 4;
	*puMinorVersion = 50401;
    return S_OK;;
}

STDMETHODIMP CXcpControlHost::NotifyLoaded() 
{
    return S_OK;
}

STDMETHODIMP CXcpControlHost::NotifyError(BSTR bstrError, BSTR bstrSource, long nLine, long nColumn)
{
    return S_OK;
}

STDMETHODIMP CXcpControlHost::InvokeHandler(BSTR bstrName, VARIANT varParam1, VARIANT varParam2, VARIANT* pvarResult) 
{
    return E_NOTIMPL;
}

STDMETHODIMP CXcpControlHost::GetBaseUrl(BSTR* pbstrUrl) {

	CAtlString strPath;
	TCHAR pBuff[255];
	GetCurrentDirectory(255, pBuff);
	strPath = pBuff;
	strPath += "\\";

    *pbstrUrl = SysAllocString(strPath);

	//MessageBox(*pbstrUrl, L"GetBaseUrl", 0);
    return S_OK;
}

STDMETHODIMP CXcpControlHost::GetNamedSource(BSTR bstrSourceName, BSTR* pbstrSource) 
{    
	return E_NOTIMPL;
}

STDMETHODIMP CXcpControlHost::DownloadUrl(BSTR bstrUrl, IXcpControlDownloadCallback* pCallback, IStream** ppStream) 
{
//	MessageBox(L"DownloadUrl", L"DownloadUrl", 0);
    return S_FALSE;
}



///////////////////////////////////////////////////////////////////////////////
// CXcpControlHost Constructor/Destructor

CXcpControlHost::CXcpControlHost() 
{
}

CXcpControlHost::~CXcpControlHost() 
{
}



///////////////////////////////////////////////////////////////////////////////
// CXcpControlHost IServiceProvider Implementation

STDMETHODIMP CXcpControlHost::QueryService(REFGUID rsid, REFIID riid, void** ppvObj) {
    ATLASSERT(ppvObj != NULL);
    if (ppvObj == NULL)
        return E_POINTER;
    *ppvObj = NULL;

	//static const GUID IID_IXcpControlHost = 
	//	{ 0x1B36028E, 0xB491, 0x4bb2, { 0x85, 0x84, 0x8A, 0x9E, 0x0A, 0x67, 0x7D, 0x6E }};

    HRESULT hr = E_NOINTERFACE;

    if ((rsid == IID_IXcpControlHost) && (riid == IID_IXcpControlHost)) {
        ((IXcpControlHost*)this)->AddRef();
        *ppvObj = (IXcpControlHost*)this;
        hr = S_OK;
    }

	if ((rsid == IID_IXcpControlHost2) && (riid == IID_IXcpControlHost2)) {
        ((IXcpControlHost2*)this)->AddRef();
        *ppvObj = (IXcpControlHost2*)this;
        hr = S_OK;
    }


    return hr;
}

///////////////////////////////////////////////////////////////////////////////
// General ActiveX control embedding.


HRESULT CXcpControlHost::CreateXcpControl(HWND hWnd) 
{
    AtlAxWinInit();

    HRESULT hr;
    static const GUID IID_IXcpControl = 
		{ 0x1FB839CC, 0x116C, 0x4C9B, { 0xAE, 0x8E, 0x3D, 0xBB, 0x64, 0x96, 0xE3, 0x26 }};

	static const GUID CLSID_XcpControl = 
		{ 0xDFEAF541, 0xF3E1, 0x4c24, { 0xAC, 0xAC, 0x99, 0xC3, 0x07, 0x15, 0x08, 0x4A }};

	static const GUID IID_IXcpControl2 = 
		{ 0x1c3294f9, 0x891f, 0x49b1, { 0xBB, 0xAE, 0x49, 0x2a, 0x68, 0xBA, 0x10, 0xcc }};

//	static const GUID CLSID_XcpControl2 = 
//		{ 0xDFEAF541, 0xF3E1, 0x4c24, { 0xAC, 0xAC, 0x99, 0xC3, 0x07, 0x15, 0x08, 0x4A }};

	//static const GUID IID_IXcpControlHost2 = 
	//	{ 0xfb3ed7c4, 0x5797, 0x4b44, { 0x86, 0x95, 0x0c, 0x51, 0x2e, 0xa2, 0x7D, 0x8f }};
	
	hr = CoCreateInstance(CLSID_XcpControl, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnKnown);
    
    if (SUCCEEDED(hr)) 
	{
        CComPtr<IUnknown> spUnkContainer;
        hr = CXcpControlHost::_CreatorClass::CreateInstance(NULL, IID_IUnknown, (void**)&spUnkContainer);
        if (SUCCEEDED(hr)) 
		{
            CComPtr<IAxWinHostWindow> pAxWindow;

		    spUnkContainer->QueryInterface(IID_IAxWinHostWindow, (void**)&pAxWindow);
			pUnKnown->QueryInterface(IID_IXcpControl2, (void**)&pControl);
            hr = pAxWindow->AttachControl(pUnKnown, hWnd);            
            hControlWindow = hWnd;

			IOleInPlaceActiveObject *pObj;
			hr = pControl->QueryInterface(IID_IOleInPlaceActiveObject, (void**)&pObj);
	    }
    }
    return hr;
}

HRESULT CXcpControlHost::DestroyXcpControl()
{
    HRESULT hr = S_OK;
    if (pControl)
    {
        pControl->Release();
    }
    if (pUnKnown)
    {
        pUnKnown->Release();
    }
    return hr;
}


STDMETHODIMP CXcpControlHost::AttachControl(IUnknown* pUnKnown, HWND hWnd) {
    ReleaseAll();

    HRESULT hr = S_FALSE;
    BOOL fReleaseWindowOnFailure = FALSE;

    if ((m_hWnd != NULL) && (m_hWnd != hWnd)) {
        // Don't release the window if it's the same as the one we already subclass/own
        RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
        ReleaseWindow();
    }

    if (::IsWindow(hWnd)) {
        if (m_hWnd != hWnd) {
            // Don't need to subclass the window if we already own it
            SubclassWindow(hWnd);
            fReleaseWindowOnFailure = TRUE;
        }

        hr = ActivateXcpControl(pUnKnown);
        if (FAILED(hr)) {
            ReleaseAll();

            if (m_hWnd != NULL) {
                RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);

                if (fReleaseWindowOnFailure) {
                    // We subclassed the window in an attempt to create this control, so we unsubclass on failure
                    ReleaseWindow();
                }
            }
        }
    }
    return hr;
}

HRESULT CXcpControlHost::ActivateXcpControl(IUnknown* pUnKnown) 
{
    if (pUnKnown == NULL)
	{
        return S_OK;
    }

    m_spUnknown = pUnKnown;

    HRESULT hr = S_OK;
    pUnKnown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);
    if (m_spOleObject) 
	{
        m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);
        if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) 
		{
            CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
            m_spOleObject->SetClientSite(spClientSite);
        }

        CComQIPtr<IPersistPropertyBag> pPersist(m_spOleObject);

        if (pPersist != NULL) 
		{
            IPropertyBag* pPropBag = (IPropertyBag*)new CXcpPropertyBag();
            pPropBag->AddRef();

            pPersist->Load((IPropertyBag*)pPropBag, NULL);
            pPropBag->Release();
        }

        if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) 
		{
            CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
            m_spOleObject->SetClientSite(spClientSite);
        }

        m_dwViewObjectType = 0;
        hr = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**) &m_spViewObject);
        if (FAILED(hr)) 
		{
            hr = m_spOleObject->QueryInterface(__uuidof(IViewObject2), (void**) &m_spViewObject);
            if (SUCCEEDED(hr)) {
                m_dwViewObjectType = 3;
            }
        }
        else {
            m_dwViewObjectType = 7;
        }

        if (FAILED(hr)) 
		{
            hr = m_spOleObject->QueryInterface(__uuidof(IViewObject), (void**) &m_spViewObject);
            if (SUCCEEDED(hr))
                m_dwViewObjectType = 1;
        }

        CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());
        m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);
        if (m_spViewObject) 
		{
            m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
        }

        m_spOleObject->SetHostNames(OLESTR("AXWIN"), NULL);

        if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0) 
		{
            GetClientRect(&m_rcPos);

            m_pxSize.cx =  m_rcPos.right - m_rcPos.left;
            m_pxSize.cy =  m_rcPos.bottom - m_rcPos.top;
            AtlPixelToHiMetric(&m_pxSize, &m_hmSize);
            m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);
            m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);
            AtlHiMetricToPixel(&m_hmSize, &m_pxSize);
            m_rcPos.right = m_rcPos.left + m_pxSize.cx ;
            m_rcPos.bottom = m_rcPos.top + m_pxSize.cy ;

            CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
            hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos);
            RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
        }
    }

    CComPtr<IObjectWithSite> spSite;
    pUnKnown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
    if (spSite != NULL) 
	{
        spSite->SetSite(GetControllingUnknown());
    }

    return hr;
}

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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Syed Aftab Hassan Naqvi

Comments and Discussions