Click here to Skip to main content
15,860,972 members
Articles / Desktop Programming / WTL

Form Designer

26 Jul 2021CPOL24 min read 349.8K   82.5K   230  
Component for adding scriptable forms capabilities to an application.
// DDAxHostWindow.cpp: implementation of the CDDAxHostWindow class.
//
// Author : David Shepherd
//			Copyright (c) 2003, DaeDoe-Software
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DDAxHostWindow.h"

/////////////////////////////////////////////////////////////////////////////
// CDDAxHostWindow

LRESULT CDDAxHostWindow::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
TRY
	// if a windowed control is being hosted
	if(m_spViewObject!=NULL and m_bWindowless==FALSE)
	{
		// get the paint device context
		CPaintDC dcPaint(*this);
		if(dcPaint==NULL)
		{
			throw std::exception();
		}
		// get the client rect
		CRect ClientRect(0,0,0,0);
		if(GetClientRect(ClientRect)==FALSE)
		{
			throw std::exception();
		}
		// translate the background color to an RGB value
		COLORREF RGBBackColor=RGB(0,0,0);
		if(!SUCCEEDED(OleTranslateColor(m_clrBackground,NULL,&RGBBackColor)))
		{
			throw std::exception();
		}
		// fill in the background
		dcPaint.FillSolidRect(ClientRect,RGBBackColor);
	}
	else
	{
		// let the base class handle the message
		return CAxHostWindow::OnPaint(uMsg,wParam,lParam,bHandled);
	}
CATCH_ALL
	return 0;
}

LRESULT CDDAxHostWindow::OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
/////////////////////////////////////////////////////////////////////////////
// copied from CAxHostWindow with any changes marked as CHANGED
// todo : keep this synchronised with ATL
/////////////////////////////////////////////////////////////////////////////
	{
		bHandled = FALSE;
		// CHANGED - check the status for reasons other than
		// OLEMISC_NOUIACTIVATE to not give focus to the control
		if (m_dwMiscStatus & (
			OLEMISC_ACTSLIKELABEL		|
			OLEMISC_INVISIBLEATRUNTIME	|
			OLEMISC_NOUIACTIVATE))
		{
			if (m_spOleObject != NULL && !m_bInPlaceActive)
			{
				CComPtr<IOleClientSite> spClientSite;
				GetControllingUnknown()->QueryInterface(__uuidof(IOleClientSite), (void**)&spClientSite);
				if (spClientSite != NULL)
					m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos);
			}
			// CHANGED - do not activate the control
			bHandled=TRUE;
			return MA_NOACTIVATEANDEAT;
		}
		else
		{
			BOOL b;
			OnSetFocus(0, 0, 0, b);
		}
		return 0;
	}
}

HRESULT CDDAxHostWindow::ActivateAx(IUnknown* pUnkControl, bool bInited, IStream* pStream)
{
/////////////////////////////////////////////////////////////////////////////
// copied from CAxHostWindow with any changes marked as CHANGED
// todo : keep this synchronised with ATL
/////////////////////////////////////////////////////////////////////////////
	{
		if (pUnkControl == NULL)
			return S_OK;

		m_spUnknown = pUnkControl;

		HRESULT hr = S_OK;
		pUnkControl->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);
			}

			if (!bInited) // If user hasn't initialized the control, initialize/load using IPersistStreamInit or IPersistStream
			{
				CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);
				if (spPSI)
				{
					if (pStream)
						hr = spPSI->Load(pStream);
					else
						hr = spPSI->InitNew();
				}
				else if (pStream)
				{
					CComQIPtr<IPersistStream> spPS(m_spOleObject);
					if (spPS)
						hr = spPS->Load(pStream);
				}

				if (FAILED(hr)) // If the initialization of the control failed...
				{
					// Clean up and return
					if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)
						m_spOleObject->SetClientSite(NULL);

					m_dwMiscStatus = 0;
					m_spOleObject.Release();
					m_spUnknown.Release();

					return hr;
				}
			}

			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);

			// CHANGED - ignore the invisible at runtime status
			//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;
		pUnkControl->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);
		if (spSite != NULL)
			spSite->SetSite(GetControllingUnknown());

		return hr;
	}
}

STDMETHODIMP CDDAxHostWindow::AttachControl(IUnknown* pUnkControl, HWND hWnd)
{
/////////////////////////////////////////////////////////////////////////////
// copied from CAxHostWindow with any changes marked as CHANGED
// todo : keep this synchronised with ATL
/////////////////////////////////////////////////////////////////////////////
	{
		HRESULT hr = S_FALSE;

		ReleaseAll();

		bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window

		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);
				bReleaseWindowOnFailure = true;
			}

			hr = ActivateAx(pUnkControl, true, NULL);

			if (FAILED(hr))
			{
				ReleaseAll();

				if (m_hWnd != NULL)
				{
					RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
					if (bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure
						ReleaseWindow();
				}
			}
		}
		return hr;
	}
}

STDMETHODIMP CDDAxHostWindow::CreateControlLicEx(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink, BSTR bstrLic)
{
/////////////////////////////////////////////////////////////////////////////
// copied from CAxHostWindow with any changes marked as CHANGED
// todo : keep this synchronised with ATL
/////////////////////////////////////////////////////////////////////////////
	{
		ATLASSERT(ppUnk != NULL);
		if (ppUnk == NULL)
			return E_POINTER;
		*ppUnk = NULL;
		HRESULT hr = S_FALSE;
		bool bReleaseWindowOnFailure = false; // Used to keep track of whether we subclass the window

		ReleaseAll();

		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))
		{
			USES_CONVERSION;
			if (m_hWnd != hWnd) // Don't need to subclass the window if we already own it
			{
				SubclassWindow(hWnd);
				bReleaseWindowOnFailure = true;
			}
			if (m_clrBackground == NULL)
			{
				if (IsParentDialog())
					m_clrBackground = GetSysColor(COLOR_BTNFACE);
				else
					m_clrBackground = GetSysColor(COLOR_WINDOW);
			}

			bool bWasHTML = false;

			hr = CreateNormalizedObject(lpszTricsData, __uuidof(IUnknown), (void**)ppUnk, bWasHTML, bstrLic);

			if (SUCCEEDED(hr))
				hr = ActivateAx(*ppUnk, false, pStream);

			// Try to hook up any sink the user might have given us.
			m_iidSink = iidAdvise;
			if(SUCCEEDED(hr) && *ppUnk && punkSink)
				AtlAdvise(*ppUnk, punkSink, m_iidSink, &m_dwAdviseSink);

			if (SUCCEEDED(hr) && bWasHTML && *ppUnk != NULL)
			{
				if ((GetStyle() & (WS_VSCROLL | WS_HSCROLL)) == 0)
					m_dwDocHostFlags |= DOCHOSTUIFLAG_SCROLL_NO;
				else
				{
					DWORD dwStyle = GetStyle();
					SetWindowLong(GWL_STYLE, dwStyle & ~(WS_VSCROLL | WS_HSCROLL));
					SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOSIZE | SWP_FRAMECHANGED | SWP_DRAWFRAME);
				}

				CComPtr<IUnknown> spUnk(*ppUnk);
				// Is it just plain HTML?
				USES_CONVERSION;
				if ((lpszTricsData[0] == OLECHAR('M') || lpszTricsData[0] == OLECHAR('m')) &&
					(lpszTricsData[1] == OLECHAR('S') || lpszTricsData[1] == OLECHAR('s')) &&
					(lpszTricsData[2] == OLECHAR('H') || lpszTricsData[2] == OLECHAR('h')) &&
					(lpszTricsData[3] == OLECHAR('T') || lpszTricsData[3] == OLECHAR('t')) &&
					(lpszTricsData[4] == OLECHAR('M') || lpszTricsData[4] == OLECHAR('m')) &&
					(lpszTricsData[5] == OLECHAR('L') || lpszTricsData[5] == OLECHAR('l')) &&
					(lpszTricsData[6] == OLECHAR(':')))
				{
					// Just HTML: load the HTML data into the document

					UINT nCreateSize = (ocslen(lpszTricsData) - 7) * sizeof(OLECHAR);
					HGLOBAL hGlobal = GlobalAlloc(GHND, nCreateSize);
					if (hGlobal)
					{
						CComPtr<IStream> spStream;
						BYTE* pBytes = (BYTE*) GlobalLock(hGlobal);
						memcpy(pBytes, lpszTricsData + 7, nCreateSize);
						GlobalUnlock(hGlobal);
						hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStream);
						if (SUCCEEDED(hr))
						{
							CComPtr<IPersistStreamInit> spPSI;
							hr = spUnk->QueryInterface(__uuidof(IPersistStreamInit), (void**)&spPSI);
							if (SUCCEEDED(hr))
								hr = spPSI->Load(spStream);
						}
					}
					else
						hr = E_OUTOFMEMORY;
				}
				else
				{
					CComPtr<IWebBrowser2> spBrowser;
					spUnk->QueryInterface(__uuidof(IWebBrowser2), (void**)&spBrowser);
					if (spBrowser)
					{
						CComVariant ve;
						CComVariant vurl(lpszTricsData);
						spBrowser->put_Visible(ATL_VARIANT_TRUE);
						spBrowser->Navigate2(&vurl, &ve, &ve, &ve, &ve);
					}
				}

			}
			if (FAILED(hr) || m_spUnknown == NULL)
			{
				// We don't have a control or something failed so release
				ReleaseAll();

				if (m_hWnd != NULL)
				{
					RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
					if (FAILED(hr) && bReleaseWindowOnFailure) // We subclassed the window in an attempt to create this control, so we unsubclass on failure
						ReleaseWindow();
				}
			}
		}
		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
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions