// 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;
}
}