windows-nt/Source/XPSP1/NT/public/sdk/inc/atl30/atlhost.h
2020-09-26 16:20:57 +08:00

2599 lines
70 KiB
C++

// This is a part of the Active Template Library.
// Copyright (C) 1996-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.
#ifndef __ATLHOST_H__
#define __ATLHOST_H__
#include <urlmon.h>
#include <mshtml.h>
#include <mshtmhst.h>
#include <exdisp.h>
#ifndef _ATL_AXHOST
#define _ATL_AXHOST
#endif //_ATL_AXHOST
#include <atlwin.h>
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLCOM_H__
#error atlhost.h requires atlcom.h to be included first
#endif
#ifdef _ATL_NO_HOSTING
#error atlhost.h requires Hosting support (_ATL_NO_HOSTING is defined)
#endif //_ATL_NO_HOSTING
namespace ATL
{
//AtlAxWinTerm is not exported
inline BOOL AtlAxWinTerm()
{
#ifndef _ATL_DLL //don't unregister DLL's version
UnregisterClass(CAxWindow::GetWndClassName(), _Module.GetModuleInstance());
#endif
return TRUE;
}
// Define this to host SHDOCVW rather than MSHTML
#define SHDOCVW
UINT __declspec(selectany) WM_ATLGETHOST = 0;
UINT __declspec(selectany) WM_ATLGETCONTROL = 0;
//EXTERN_C const IID IID_IHTMLDocument2 = {0x332C4425,0x26CB,0x11D0,{0xB4,0x83,0x00,0xC0,0x4F,0xD9,0x01,0x19}};
typedef HRESULT (__stdcall *typeMkParseDisplayName)(IBindCtx*, LPCWSTR , ULONG*, LPMONIKER*);
static HRESULT CreateNormalizedObject(LPCOLESTR lpszTricsData, REFIID riid, void** ppvObj, bool& bWasHTML)
{
ATLASSERT(ppvObj);
CLSID clsid;
HRESULT hr = E_FAIL;
BOOL bInited = FALSE;
bWasHTML = false;
*ppvObj = NULL;
if (lpszTricsData == NULL || lpszTricsData[0] == 0)
return S_OK;
// Is it 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(':')))
{
// It's HTML, so let's create mshtml
hr = CoCreateInstance(CLSID_HTMLDocument, NULL, CLSCTX_SERVER, riid, ppvObj);
bWasHTML = true;
}
if (FAILED(hr))
{
// Can't be clsid, or progid if length is grater than 255
if (ocslen(lpszTricsData) < 255)
{
if (lpszTricsData[0] == '{') // Is it a CLSID?
hr = CLSIDFromString((LPOLESTR)lpszTricsData, &clsid);
else
hr = CLSIDFromProgID((LPOLESTR)lpszTricsData, &clsid); // How about a ProgID?
if (SUCCEEDED(hr)) // Aha, it was one of those two
hr = CoCreateInstance(clsid, NULL, CLSCTX_SERVER, riid, ppvObj);
}
if (FAILED(hr))
{
// Last guess - it must be either a URL so let's create shdocvw
hr = CoCreateInstance(CLSID_WebBrowser, NULL, CLSCTX_SERVER, riid, ppvObj);
bWasHTML = true;
}
}
if (SUCCEEDED(hr) && bInited)
hr = S_FALSE;
return hr;
}
class ATL_NO_VTABLE CAxFrameWindow :
public CComObjectRootEx<CComObjectThreadModel>,
public CWindowImpl<CAxFrameWindow>,
public IOleInPlaceFrame
{
public:
CAxFrameWindow()
{
}
void FinalRelease()
{
m_spActiveObject.Release();
if (m_hWnd)
DestroyWindow();
}
DECLARE_POLY_AGGREGATABLE(CAxFrameWindow)
BEGIN_COM_MAP(CAxFrameWindow)
COM_INTERFACE_ENTRY(IOleInPlaceFrame)
COM_INTERFACE_ENTRY(IOleInPlaceUIWindow)
COM_INTERFACE_ENTRY(IOleWindow)
END_COM_MAP()
DECLARE_EMPTY_MSG_MAP()
// IOleWindow
STDMETHOD(GetWindow)(HWND* phwnd)
{
if (m_hWnd == NULL)
{
RECT rcPos = { CW_USEDEFAULT, 0, 0, 0 };
Create(NULL, rcPos, _T("AXWIN Frame Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL);
}
*phwnd = m_hWnd;
return S_OK;
}
STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/)
{
return S_OK;
}
// IOleInPlaceUIWindow
STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/)
{
return S_OK;
}
STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
{
return INPLACE_E_NOTOOLSPACE;
}
STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
{
return S_OK;
}
STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/)
{
m_spActiveObject = pActiveObject;
return S_OK;
}
// IOleInPlaceFrameWindow
STDMETHOD(InsertMenus)(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
{
return S_OK;
}
STDMETHOD(SetMenu)(HMENU /*hmenuShared*/, HOLEMENU /*holemenu*/, HWND /*hwndActiveObject*/)
{
return S_OK;
}
STDMETHOD(RemoveMenus)(HMENU /*hmenuShared*/)
{
return S_OK;
}
STDMETHOD(SetStatusText)(LPCOLESTR /*pszStatusText*/)
{
return S_OK;
}
STDMETHOD(EnableModeless)(BOOL /*fEnable*/)
{
return S_OK;
}
STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, WORD /*wID*/)
{
return S_FALSE;
}
CComPtr<IOleInPlaceActiveObject> m_spActiveObject;
};
class ATL_NO_VTABLE CAxUIWindow :
public CComObjectRootEx<CComObjectThreadModel>,
public CWindowImpl<CAxUIWindow>,
public IOleInPlaceUIWindow
{
public:
CAxUIWindow()
{
}
void FinalRelease()
{
m_spActiveObject.Release();
if (m_hWnd)
DestroyWindow();
}
DECLARE_POLY_AGGREGATABLE(CAxUIWindow)
BEGIN_COM_MAP(CAxUIWindow)
COM_INTERFACE_ENTRY(IOleInPlaceUIWindow)
COM_INTERFACE_ENTRY(IOleWindow)
END_COM_MAP()
DECLARE_EMPTY_MSG_MAP()
// IOleWindow
STDMETHOD(GetWindow)(HWND* phwnd)
{
if (m_hWnd == NULL)
{
RECT rcPos = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 };
Create(NULL, rcPos, _T("AXWIN UI Window"), WS_OVERLAPPEDWINDOW, 0, (UINT)NULL);
}
*phwnd = m_hWnd;
return S_OK;
}
STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/)
{
return S_OK;
}
// IOleInPlaceUIWindow
STDMETHOD(GetBorder)(LPRECT /*lprectBorder*/)
{
return S_OK;
}
STDMETHOD(RequestBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
{
return INPLACE_E_NOTOOLSPACE;
}
STDMETHOD(SetBorderSpace)(LPCBORDERWIDTHS /*pborderwidths*/)
{
return S_OK;
}
STDMETHOD(SetActiveObject)(IOleInPlaceActiveObject* pActiveObject, LPCOLESTR /*pszObjName*/)
{
m_spActiveObject = pActiveObject;
return S_OK;
}
CComPtr<IOleInPlaceActiveObject> m_spActiveObject;
};
/////////////////////////////////////////////////////////////////////////////
// CAxHostWindow
// This class is not cocreateable
class ATL_NO_VTABLE CAxHostWindow :
public CComCoClass<CAxHostWindow , &CLSID_NULL>,
public CComObjectRootEx<CComSingleThreadModel>,
public CWindowImpl<CAxHostWindow>,
public IAxWinHostWindow,
public IOleClientSite,
public IOleInPlaceSiteWindowless,
public IOleControlSite,
public IOleContainer,
public IObjectWithSiteImpl<CAxHostWindow>,
public IServiceProvider,
public IAdviseSink,
#ifndef _ATL_NO_DOCHOSTUIHANDLER
public IDocHostUIHandler,
#endif
public IDispatchImpl<IAxWinAmbientDispatch, &IID_IAxWinAmbientDispatch, &LIBID_ATLLib>
{
public:
// ctor/dtor
CAxHostWindow()
{
m_bInPlaceActive = FALSE;
m_bUIActive = FALSE;
m_bMDIApp = FALSE;
m_bWindowless = FALSE;
m_bCapture = FALSE;
m_bHaveFocus = FALSE;
// Initialize ambient properties
m_bCanWindowlessActivate = TRUE;
m_bUserMode = TRUE;
m_bDisplayAsDefault = FALSE;
m_clrBackground = NULL;
m_clrForeground = GetSysColor(COLOR_WINDOWTEXT);
m_lcidLocaleID = LOCALE_USER_DEFAULT;
m_bMessageReflect = true;
m_bReleaseAll = FALSE;
m_bSubclassed = FALSE;
m_dwAdviseSink = 0xCDCDCDCD;
m_dwDocHostFlags = DOCHOSTUIFLAG_NO3DBORDER;
m_dwDocHostDoubleClickFlags = DOCHOSTUIDBLCLK_DEFAULT;
m_bAllowContextMenu = true;
m_bAllowShowUI = false;
}
~CAxHostWindow()
{
}
void FinalRelease()
{
ReleaseAll();
}
virtual void OnFinalMessage(HWND /*hWnd*/)
{
GetControllingUnknown()->Release();
}
DECLARE_NO_REGISTRY()
DECLARE_POLY_AGGREGATABLE(CAxHostWindow)
DECLARE_GET_CONTROLLING_UNKNOWN()
BEGIN_COM_MAP(CAxHostWindow)
COM_INTERFACE_ENTRY2(IDispatch, IAxWinAmbientDispatch)
COM_INTERFACE_ENTRY(IAxWinHostWindow)
COM_INTERFACE_ENTRY(IOleClientSite)
COM_INTERFACE_ENTRY(IOleInPlaceSiteWindowless)
COM_INTERFACE_ENTRY(IOleInPlaceSiteEx)
COM_INTERFACE_ENTRY(IOleInPlaceSite)
COM_INTERFACE_ENTRY(IOleWindow)
COM_INTERFACE_ENTRY(IOleControlSite)
COM_INTERFACE_ENTRY(IOleContainer)
COM_INTERFACE_ENTRY(IObjectWithSite)
COM_INTERFACE_ENTRY(IServiceProvider)
COM_INTERFACE_ENTRY(IAxWinAmbientDispatch)
#ifndef _ATL_NO_DOCHOSTUIHANDLER
COM_INTERFACE_ENTRY(IDocHostUIHandler)
#endif
COM_INTERFACE_ENTRY(IAdviseSink)
END_COM_MAP()
static CWndClassInfo& GetWndClassInfo()
{
static CWndClassInfo wc =
{
{ sizeof(WNDCLASSEX), 0, StartWindowProc,
0, 0, 0, 0, 0, (HBRUSH)(COLOR_WINDOW + 1), 0, _T("AtlAxWin"), 0 },
NULL, NULL, IDC_ARROW, TRUE, 0, _T("")
};
return wc;
}
BEGIN_MSG_MAP(CAxHostWindow)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
if (m_bWindowless)
{
// Mouse messages handled when a windowless control has captured the cursor
// or if the cursor is over the control
DWORD dwHitResult = m_bCapture ? HITRESULT_HIT : HITRESULT_OUTSIDE;
if (dwHitResult == HITRESULT_OUTSIDE && m_spViewObject != NULL)
{
POINT ptMouse = { LOWORD(lParam), HIWORD(lParam) };
m_spViewObject->QueryHitPoint(DVASPECT_CONTENT, &m_rcPos, ptMouse, 0, &dwHitResult);
}
if (dwHitResult == HITRESULT_HIT)
{
MESSAGE_HANDLER(WM_MOUSEMOVE, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_SETCURSOR, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_LBUTTONUP, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_RBUTTONUP, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_MBUTTONUP, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_RBUTTONDOWN, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_MBUTTONDOWN, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_RBUTTONDBLCLK, OnWindowlessMouseMessage)
MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowlessMouseMessage)
}
}
if (m_bWindowless & m_bHaveFocus)
{
// Keyboard messages handled only when a windowless control has the focus
MESSAGE_HANDLER(WM_KEYDOWN, OnWindowMessage)
MESSAGE_HANDLER(WM_KEYUP, OnWindowMessage)
MESSAGE_HANDLER(WM_CHAR, OnWindowMessage)
MESSAGE_HANDLER(WM_DEADCHAR, OnWindowMessage)
MESSAGE_HANDLER(WM_SYSKEYDOWN, OnWindowMessage)
MESSAGE_HANDLER(WM_SYSKEYUP, OnWindowMessage)
MESSAGE_HANDLER(WM_SYSDEADCHAR, OnWindowMessage)
MESSAGE_HANDLER(WM_HELP, OnWindowMessage)
MESSAGE_HANDLER(WM_CANCELMODE, OnWindowMessage)
MESSAGE_HANDLER(WM_IME_CHAR, OnWindowMessage)
MESSAGE_HANDLER(WM_MBUTTONDBLCLK, OnWindowMessage)
MESSAGE_RANGE_HANDLER(WM_IME_SETCONTEXT, WM_IME_KEYUP, OnWindowMessage)
}
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
if(!m_bWindowless && m_bMessageReflect)
{
bHandled = TRUE;
lResult = ReflectNotifications(uMsg, wParam, lParam, bHandled);
if(bHandled)
return TRUE;
}
MESSAGE_HANDLER(WM_ATLGETHOST, OnGetUnknown)
MESSAGE_HANDLER(WM_ATLGETCONTROL, OnGetControl)
MESSAGE_HANDLER(WM_FORWARDMSG, OnForwardMsg)
END_MSG_MAP()
LRESULT OnForwardMsg(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
ATLASSERT(lParam != 0);
LPMSG lpMsg = (LPMSG)lParam;
CComQIPtr<IOleInPlaceActiveObject, &IID_IOleInPlaceActiveObject> spInPlaceActiveObject(m_spUnknown);
if(spInPlaceActiveObject)
{
if(spInPlaceActiveObject->TranslateAccelerator(lpMsg) == S_OK)
return 1;
}
return 0;
}
LRESULT OnGetUnknown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
IUnknown* pUnk = GetControllingUnknown();
pUnk->AddRef();
return (LRESULT)pUnk;
}
LRESULT OnGetControl(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
IUnknown* pUnk = m_spUnknown;
if (pUnk)
pUnk->AddRef();
return (LRESULT)pUnk;
}
void ReleaseAll()
{
if (m_bReleaseAll)
return;
m_bReleaseAll = TRUE;
if (m_spViewObject != NULL)
m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, NULL);
if(m_dwAdviseSink != 0xCDCDCDCD)
{
AtlUnadvise(m_spUnknown, m_iidSink, m_dwAdviseSink);
m_dwAdviseSink = 0xCDCDCDCD;
}
if (m_spOleObject)
{
m_spOleObject->Unadvise(m_dwOleObject);
m_spOleObject->Close(OLECLOSE_NOSAVE);
m_spOleObject->SetClientSite(NULL);
}
if (m_spUnknown != NULL)
{
CComPtr<IObjectWithSite> spSite;
m_spUnknown->QueryInterface(IID_IObjectWithSite, (void**)&spSite);
if (spSite != NULL)
spSite->SetSite(NULL);
}
m_spViewObject.Release();
m_dwViewObjectType = 0;
m_spInPlaceObjectWindowless.Release();
m_spOleObject.Release();
m_spUnknown.Release();
m_spInPlaceUIWindow.Release();
m_spInPlaceFrame.Release();
m_bInPlaceActive = FALSE;
m_bWindowless = FALSE;
m_bInPlaceActive = FALSE;
m_bUIActive = FALSE;
m_bCapture = FALSE;
m_bReleaseAll = FALSE;
}
// window message handlers
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if (m_spViewObject == NULL)
bHandled = false;
return 1;
}
LRESULT OnNCHitTest(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return HTCLIENT;
}
LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
m_bHaveFocus = TRUE;
if (!m_bReleaseAll)
{
if (m_spOleObject != NULL && !m_bInPlaceActive)
{
CComPtr<IOleClientSite> spClientSite;
GetControllingUnknown()->QueryInterface(IID_IOleClientSite, (void**)&spClientSite);
if (spClientSite != NULL)
m_spOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, spClientSite, 0, m_hWnd, &m_rcPos);
}
if(!m_bWindowless && !IsChild(::GetFocus()))
::SetFocus(::GetWindow(m_hWnd, GW_CHILD));
}
bHandled = FALSE;
return 0;
}
LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
m_bHaveFocus = FALSE;
bHandled = FALSE;
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
int nWidth = LOWORD(lParam); // width of client area
int nHeight = HIWORD(lParam); // height of client area
m_rcPos.right = m_rcPos.left + nWidth;
m_rcPos.bottom = m_rcPos.top + nHeight;
m_pxSize.cx = m_rcPos.right - m_rcPos.left;
m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;
AtlPixelToHiMetric(&m_pxSize, &m_hmSize);
if (m_spOleObject)
m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);
if (m_spInPlaceObjectWindowless)
m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
if (m_bWindowless)
InvalidateRect(NULL, TRUE);
bHandled = FALSE;
return 0;
}
LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
GetControllingUnknown()->AddRef();
ReleaseAll();
DefWindowProc(uMsg, wParam, lParam);
bHandled = FALSE;
return 0;
}
LRESULT OnWindowMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT lRes = 0;
HRESULT hr = S_FALSE;
if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless)
hr = m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes);
if (hr == S_FALSE)
bHandled = FALSE;
return lRes;
}
LRESULT OnWindowlessMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT lRes = 0;
if (m_bInPlaceActive && m_bWindowless && m_spInPlaceObjectWindowless)
m_spInPlaceObjectWindowless->OnWindowMessage(uMsg, wParam, lParam, &lRes);
bHandled = FALSE;
return lRes;
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if (m_spViewObject == NULL)
{
PAINTSTRUCT ps;
HDC hdc = ::BeginPaint(m_hWnd, &ps);
if (hdc == NULL)
return 0;
RECT rcClient;
GetClientRect(&rcClient);
HBRUSH hbrBack = CreateSolidBrush(m_clrBackground);
FillRect(hdc, &rcClient, hbrBack);
DeleteObject(hbrBack);
::EndPaint(m_hWnd, &ps);
return 1;
}
if (m_spViewObject && m_bWindowless)
{
PAINTSTRUCT ps;
HDC hdc = ::BeginPaint(m_hWnd, &ps);
if (hdc == NULL)
return 0;
RECT rcClient;
GetClientRect(&rcClient);
HBITMAP hBitmap = CreateCompatibleBitmap(hdc, rcClient.right - rcClient.left, rcClient.bottom - rcClient.top);
HDC hdcCompatible = ::CreateCompatibleDC(hdc);
HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcCompatible, hBitmap);
HBRUSH hbrBack = CreateSolidBrush(m_clrBackground);
FillRect(hdcCompatible, &rcClient, hbrBack);
DeleteObject(hbrBack);
m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdcCompatible, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL);
::BitBlt(hdc, 0, 0, rcClient.right, rcClient.bottom, hdcCompatible, 0, 0, SRCCOPY);
::SelectObject(hdcCompatible, hBitmapOld);
::DeleteObject(hBitmap);
::DeleteDC(hdcCompatible);
::EndPaint(m_hWnd, &ps);
}
else
{
bHandled = FALSE;
return 0;
}
return 1;
}
// IAxWinHostWindow
STDMETHOD(CreateControl)(LPCOLESTR lpTricsData, HWND hWnd, IStream* pStream)
{
CComPtr<IUnknown> p;
return CreateControlEx(lpTricsData, hWnd, pStream, &p, IID_NULL, NULL);
}
STDMETHOD(CreateControlEx)(LPCOLESTR lpszTricsData, HWND hWnd, IStream* pStream, IUnknown** ppUnk, REFIID iidAdvise, IUnknown* punkSink)
{
HRESULT hr = S_FALSE;
ReleaseAll();
if (m_hWnd != NULL)
{
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
ReleaseWindow();
}
if (::IsWindow(hWnd))
{
USES_CONVERSION;
SubclassWindow(hWnd);
if (m_clrBackground == NULL)
{
if (IsParentDialog())
m_clrBackground = GetSysColor(COLOR_BTNFACE);
else
m_clrBackground = GetSysColor(COLOR_WINDOW);
}
bool bWasHTML;
hr = CreateNormalizedObject(lpszTricsData, IID_IUnknown, (void**)ppUnk, bWasHTML);
bool bInited = hr == S_FALSE;
if (SUCCEEDED(hr))
hr = ActivateAx(*ppUnk, bInited, 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, eh?
CComPtr<IPersistStreamInit> spPSI;
hr = spUnk->QueryInterface(IID_IPersistStreamInit, (void**)&spPSI);
spPSI->InitNew();
bInited = TRUE;
CComPtr<IHTMLDocument2> spHTMLDoc2;
hr = spUnk->QueryInterface(IID_IHTMLDocument2, (void**)&spHTMLDoc2);
if (SUCCEEDED(hr))
{
CComPtr<IHTMLElement> spHTMLBody;
hr = spHTMLDoc2->get_body(&spHTMLBody);
if (SUCCEEDED(hr))
hr = spHTMLBody->put_innerHTML(CComBSTR(lpszTricsData + 7));
}
}
else
{
CComPtr<IWebBrowser2> spBrowser;
spUnk->QueryInterface(IID_IWebBrowser2, (void**)&spBrowser);
if (spBrowser)
{
CComVariant ve;
CComVariant vurl(lpszTricsData);
#pragma warning(disable: 4310) // cast truncates constant value
spBrowser->put_Visible(VARIANT_TRUE);
#pragma warning(default: 4310) // cast truncates constant value
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))
ReleaseWindow();
}
}
}
return hr;
}
STDMETHOD(AttachControl)(IUnknown* pUnkControl, HWND hWnd)
{
HRESULT hr = S_FALSE;
ReleaseAll();
if (!::IsWindow(hWnd))
hWnd = NULL;
if (m_hWnd != NULL && m_hWnd != hWnd)
{
RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE | RDW_INTERNALPAINT | RDW_FRAME);
ReleaseWindow();
}
if (hWnd)
{
if (m_hWnd != hWnd)
SubclassWindow(hWnd);
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);
ReleaseWindow();
}
}
}
return hr;
}
STDMETHOD(QueryControl)(REFIID riid, void** ppvObject)
{
HRESULT hr = E_POINTER;
if (ppvObject)
{
if (m_spUnknown)
{
hr = m_spUnknown->QueryInterface(riid, ppvObject);
}
else
{
*ppvObject = NULL;
hr = OLE_E_NOCONNECTION;
}
}
return hr;
}
STDMETHOD(SetExternalDispatch)(IDispatch* pDisp)
{
m_spExternalDispatch = pDisp;
return S_OK;
}
STDMETHOD(SetExternalUIHandler)(IDocHostUIHandlerDispatch* pUIHandler)
{
#ifndef _ATL_NO_DOCHOSTUIHANDLER
m_spIDocHostUIHandlerDispatch = pUIHandler;
#endif
return S_OK;
}
#ifndef _ATL_NO_DOCHOSTUIHANDLER
// IDocHostUIHandler
// MSHTML requests to display its context menu
STDMETHOD(ShowContextMenu)(DWORD dwID, POINT* pptPosition, IUnknown* pCommandTarget, IDispatch* pDispatchObjectHit)
{
HRESULT hr = m_bAllowContextMenu ? S_FALSE : S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
m_spIDocHostUIHandlerDispatch->ShowContextMenu(
dwID,
pptPosition->x,
pptPosition->y,
pCommandTarget,
pDispatchObjectHit,
&hr);
return hr;
}
// Called at initialisation to find UI styles from container
STDMETHOD(GetHostInfo)(DOCHOSTUIINFO* pInfo)
{
if (pInfo == NULL)
return E_POINTER;
if (m_spIDocHostUIHandlerDispatch != NULL)
return m_spIDocHostUIHandlerDispatch->GetHostInfo(&pInfo->dwFlags, &pInfo->dwDoubleClick);
pInfo->dwFlags = m_dwDocHostFlags;
pInfo->dwDoubleClick = m_dwDocHostDoubleClickFlags;
return S_OK;
}
// Allows the host to replace the IE4/MSHTML menus and toolbars.
STDMETHOD(ShowUI)(DWORD dwID, IOleInPlaceActiveObject* pActiveObject, IOleCommandTarget* pCommandTarget, IOleInPlaceFrame* pFrame, IOleInPlaceUIWindow* pDoc)
{
HRESULT hr = m_bAllowShowUI ? S_FALSE : S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
m_spIDocHostUIHandlerDispatch->ShowUI(
dwID,
pActiveObject,
pCommandTarget,
pFrame,
pDoc,
&hr);
return hr;
}
// Called when IE4/MSHTML removes its menus and toolbars.
STDMETHOD(HideUI)()
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
hr = m_spIDocHostUIHandlerDispatch->HideUI();
return hr;
}
// Notifies the host that the command state has changed.
STDMETHOD(UpdateUI)()
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
hr = m_spIDocHostUIHandlerDispatch->UpdateUI();
return hr;
}
// Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::EnableModeless
STDMETHOD(EnableModeless)(BOOL fEnable)
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
#pragma warning(disable: 4310) // cast truncates constant value
hr = m_spIDocHostUIHandlerDispatch->EnableModeless(fEnable ? VARIANT_TRUE : VARIANT_FALSE);
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
// Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnDocWindowActivate
STDMETHOD(OnDocWindowActivate)(BOOL fActivate)
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
#pragma warning(disable: 4310) // cast truncates constant value
hr = m_spIDocHostUIHandlerDispatch->OnDocWindowActivate(fActivate ? VARIANT_TRUE : VARIANT_FALSE);
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
// Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::OnFrameWindowActivate.
STDMETHOD(OnFrameWindowActivate)(BOOL fActivate)
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
#pragma warning(disable: 4310) // cast truncates constant value
hr = m_spIDocHostUIHandlerDispatch->OnFrameWindowActivate(fActivate ? VARIANT_TRUE : VARIANT_FALSE);
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
// Called from the IE4/MSHTML implementation of IOleInPlaceActiveObject::ResizeBorder.
STDMETHOD(ResizeBorder)(LPCRECT prcBorder, IOleInPlaceUIWindow* pUIWindow, BOOL fFrameWindow)
{
HRESULT hr = S_OK;
if (m_spIDocHostUIHandlerDispatch != NULL)
#pragma warning(disable: 4310) // cast truncates constant value
hr = m_spIDocHostUIHandlerDispatch->ResizeBorder(
prcBorder->left,
prcBorder->top,
prcBorder->right,
prcBorder->bottom,
pUIWindow,
fFrameWindow ? VARIANT_TRUE : VARIANT_FALSE);
#pragma warning(default: 4310) // cast truncates constant value
return hr;
}
// Called by IE4/MSHTML when IOleInPlaceActiveObject::TranslateAccelerator or IOleControlSite::TranslateAccelerator is called.
STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, const GUID* pguidCmdGroup, DWORD nCmdID)
{
HRESULT hr = S_FALSE;
if (m_spIDocHostUIHandlerDispatch != NULL)
m_spIDocHostUIHandlerDispatch->TranslateAccelerator(
(DWORD)(DWORD_PTR)lpMsg->hwnd, //REVIEW
lpMsg->message,
(DWORD)lpMsg->wParam, //REVIEW
(DWORD)lpMsg->lParam, //REVIEW
CComBSTR(*pguidCmdGroup),
nCmdID,
&hr);
return hr;
}
// Returns the registry key under which IE4/MSHTML stores user preferences.
// Returns S_OK if successful, or S_FALSE otherwise. If S_FALSE, IE4/MSHTML will default to its own user options.
STDMETHOD(GetOptionKeyPath)(BSTR* pbstrKey, DWORD dwReserved)
{
HRESULT hr = S_FALSE;
if (pbstrKey == NULL)
return E_POINTER;
*pbstrKey = NULL;
if (m_spIDocHostUIHandlerDispatch != NULL)
{
hr = m_spIDocHostUIHandlerDispatch->GetOptionKeyPath(pbstrKey, dwReserved);
if (FAILED(hr) || *pbstrKey == NULL)
hr = S_FALSE;
}
else
{
if (m_bstrOptionKeyPath.m_str != NULL)
{
*pbstrKey = m_bstrOptionKeyPath.Copy();
hr = S_OK;
}
}
return hr;
}
// Called by IE4/MSHTML when it is being used as a drop target to allow the host to supply an alternative IDropTarget
STDMETHOD(GetDropTarget)(IDropTarget* pDropTarget, IDropTarget** ppDropTarget)
{
HRESULT hr = E_NOTIMPL;
if (ppDropTarget == NULL)
return E_POINTER;
*ppDropTarget = NULL;
if (m_spIDocHostUIHandlerDispatch != NULL)
{
CComPtr<IUnknown> spUnk;
hr = m_spIDocHostUIHandlerDispatch->GetDropTarget(pDropTarget, &spUnk);
if (spUnk)
hr = spUnk->QueryInterface(IID_IDropTarget, (void**)ppDropTarget);
if (FAILED(hr) || *ppDropTarget == NULL)
hr = S_FALSE;
}
return hr;
}
// Called by IE4/MSHTML to obtain the host's IDispatch interface
STDMETHOD(GetExternal)(IDispatch** ppDispatch)
{
HRESULT hr = E_NOINTERFACE;
if (ppDispatch == NULL)
return E_POINTER;
*ppDispatch = NULL;
if (m_spIDocHostUIHandlerDispatch != NULL)
{
hr = m_spIDocHostUIHandlerDispatch->GetExternal(ppDispatch);
if (FAILED(hr) || *ppDispatch == NULL)
hr = E_NOINTERFACE;
}
else
{
// return the IDispatch we have for extending the object Model
if (ppDispatch != NULL)
{
m_spExternalDispatch.CopyTo(ppDispatch);
hr = S_OK;
}
else
hr = E_POINTER;
}
return hr;
}
// Called by IE4/MSHTML to allow the host an opportunity to modify the URL to be loaded
STDMETHOD(TranslateUrl)(DWORD dwTranslate, OLECHAR* pchURLIn, OLECHAR** ppchURLOut)
{
HRESULT hr = S_FALSE;
if (ppchURLOut == NULL)
return E_POINTER;
*ppchURLOut = NULL;
if (m_spIDocHostUIHandlerDispatch != NULL)
{
CComBSTR bstrURLOut;
hr = m_spIDocHostUIHandlerDispatch->TranslateUrl(dwTranslate, CComBSTR(pchURLIn), &bstrURLOut);
if (SUCCEEDED(hr) && bstrURLOut.m_str != NULL)
{
UINT nLen = (bstrURLOut.Length() + 1) * 2;
*ppchURLOut = (OLECHAR*) CoTaskMemAlloc(nLen);
if (*ppchURLOut == NULL)
return E_OUTOFMEMORY;
memcpy(*ppchURLOut, bstrURLOut.m_str, nLen);
}
else
hr = S_FALSE;
}
return hr;
}
// Called on the host by IE4/MSHTML to allow the host to replace IE4/MSHTML's data object.
// This allows the host to block certain clipboard formats or support additional clipboard formats.
STDMETHOD(FilterDataObject)(IDataObject* pDO, IDataObject** ppDORet)
{
HRESULT hr = S_FALSE;
if (ppDORet == NULL)
return E_POINTER;
*ppDORet = NULL;
if (m_spIDocHostUIHandlerDispatch != NULL)
{
CComPtr<IUnknown> spUnk;
hr = m_spIDocHostUIHandlerDispatch->FilterDataObject(pDO, &spUnk);
if (spUnk)
hr = QueryInterface(IID_IDataObject, (void**)ppDORet);
if (FAILED(hr) || *ppDORet == NULL)
hr = S_FALSE;
}
return hr;
}
#endif
HRESULT FireAmbientPropertyChange(DISPID dispChanged)
{
HRESULT hr = S_OK;
CComQIPtr<IOleControl, &IID_IOleControl> spOleControl(m_spUnknown);
if (spOleControl != NULL)
hr = spOleControl->OnAmbientPropertyChange(dispChanged);
return hr;
}
// IAxWinAmbientDispatch
STDMETHOD(put_AllowWindowlessActivation)(VARIANT_BOOL bAllowWindowless)
{
m_bCanWindowlessActivate = bAllowWindowless;
return S_OK;
}
STDMETHOD(get_AllowWindowlessActivation)(VARIANT_BOOL* pbAllowWindowless)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbAllowWindowless = m_bCanWindowlessActivate ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(put_BackColor)(OLE_COLOR clrBackground)
{
m_clrBackground = clrBackground;
FireAmbientPropertyChange(DISPID_AMBIENT_BACKCOLOR);
InvalidateRect(0, FALSE);
return S_OK;
}
STDMETHOD(get_BackColor)(OLE_COLOR* pclrBackground)
{
*pclrBackground = m_clrBackground;
return S_OK;
}
STDMETHOD(put_ForeColor)(OLE_COLOR clrForeground)
{
m_clrForeground = clrForeground;
FireAmbientPropertyChange(DISPID_AMBIENT_FORECOLOR);
return S_OK;
}
STDMETHOD(get_ForeColor)(OLE_COLOR* pclrForeground)
{
*pclrForeground = m_clrForeground;
return S_OK;
}
STDMETHOD(put_LocaleID)(LCID lcidLocaleID)
{
m_lcidLocaleID = lcidLocaleID;
FireAmbientPropertyChange(DISPID_AMBIENT_LOCALEID);
return S_OK;
}
STDMETHOD(get_LocaleID)(LCID* plcidLocaleID)
{
*plcidLocaleID = m_lcidLocaleID;
return S_OK;
}
STDMETHOD(put_UserMode)(VARIANT_BOOL bUserMode)
{
m_bUserMode = bUserMode;
FireAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
return S_OK;
}
STDMETHOD(get_UserMode)(VARIANT_BOOL* pbUserMode)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbUserMode = m_bUserMode ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(put_DisplayAsDefault)(VARIANT_BOOL bDisplayAsDefault)
{
m_bDisplayAsDefault = bDisplayAsDefault;
FireAmbientPropertyChange(DISPID_AMBIENT_DISPLAYASDEFAULT);
return S_OK;
}
STDMETHOD(get_DisplayAsDefault)(VARIANT_BOOL* pbDisplayAsDefault)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbDisplayAsDefault = m_bDisplayAsDefault ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(put_Font)(IFontDisp* pFont)
{
m_spFont = pFont;
FireAmbientPropertyChange(DISPID_AMBIENT_FONT);
return S_OK;
}
STDMETHOD(get_Font)(IFontDisp** pFont)
{
if (m_spFont == NULL)
{
USES_CONVERSION;
HFONT hSystemFont = (HFONT) GetStockObject(DEFAULT_GUI_FONT);
if (hSystemFont == NULL)
hSystemFont = (HFONT) GetStockObject(SYSTEM_FONT);
LOGFONT logfont;
GetObject(hSystemFont, sizeof(logfont), &logfont);
FONTDESC fd;
fd.cbSizeofstruct = sizeof(FONTDESC);
fd.lpstrName = T2OLE(logfont.lfFaceName);
fd.sWeight = (short)logfont.lfWeight;
fd.sCharset = logfont.lfCharSet;
fd.fItalic = logfont.lfItalic;
fd.fUnderline = logfont.lfUnderline;
fd.fStrikethrough = logfont.lfStrikeOut;
long lfHeight = logfont.lfHeight;
if (lfHeight < 0)
lfHeight = -lfHeight;
int ppi;
HDC hdc;
if (m_hWnd)
{
hdc = ::GetDC(m_hWnd);
ppi = GetDeviceCaps(hdc, LOGPIXELSY);
::ReleaseDC(m_hWnd, hdc);
}
else
{
hdc = ::GetDC(GetDesktopWindow());
ppi = GetDeviceCaps(hdc, LOGPIXELSY);
::ReleaseDC(GetDesktopWindow(), hdc);
}
fd.cySize.Lo = lfHeight * 720000 / ppi;
fd.cySize.Hi = 0;
#pragma message( "Still need OleCreateFontIndirect()" )
// OleCreateFontIndirect(&fd, IID_IFontDisp, (void**) &m_spFont);
}
return m_spFont.CopyTo(pFont);
}
STDMETHOD(put_MessageReflect)(VARIANT_BOOL bMessageReflect)
{
m_bMessageReflect = bMessageReflect;
FireAmbientPropertyChange(DISPID_AMBIENT_MESSAGEREFLECT);
return S_OK;
}
STDMETHOD(get_MessageReflect)(VARIANT_BOOL* pbMessageReflect)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbMessageReflect = m_bMessageReflect ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(get_ShowGrabHandles)(VARIANT_BOOL* pbShowGrabHandles)
{
*pbShowGrabHandles = VARIANT_FALSE;
return S_OK;
}
STDMETHOD(get_ShowHatching)(VARIANT_BOOL* pbShowHatching)
{
*pbShowHatching = VARIANT_FALSE;
return S_OK;
}
STDMETHOD(put_DocHostFlags)(DWORD dwDocHostFlags)
{
m_dwDocHostFlags = dwDocHostFlags;
FireAmbientPropertyChange(DISPID_UNKNOWN);
return S_OK;
}
STDMETHOD(get_DocHostFlags)(DWORD* pdwDocHostFlags)
{
*pdwDocHostFlags = m_dwDocHostFlags;
return S_OK;
}
STDMETHOD(put_DocHostDoubleClickFlags)(DWORD dwDocHostDoubleClickFlags)
{
m_dwDocHostDoubleClickFlags = dwDocHostDoubleClickFlags;
return S_OK;
}
STDMETHOD(get_DocHostDoubleClickFlags)(DWORD* pdwDocHostDoubleClickFlags)
{
*pdwDocHostDoubleClickFlags = m_dwDocHostDoubleClickFlags;
return S_OK;
}
STDMETHOD(put_AllowContextMenu)(VARIANT_BOOL bAllowContextMenu)
{
m_bAllowContextMenu = bAllowContextMenu;
return S_OK;
}
STDMETHOD(get_AllowContextMenu)(VARIANT_BOOL* pbAllowContextMenu)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbAllowContextMenu = m_bAllowContextMenu ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(put_AllowShowUI)(VARIANT_BOOL bAllowShowUI)
{
m_bAllowShowUI = bAllowShowUI;
return S_OK;
}
STDMETHOD(get_AllowShowUI)(VARIANT_BOOL* pbAllowShowUI)
{
#pragma warning(disable: 4310) // cast truncates constant value
*pbAllowShowUI = m_bAllowShowUI ? VARIANT_TRUE : VARIANT_FALSE;
#pragma warning(default: 4310) // cast truncates constant value
return S_OK;
}
STDMETHOD(put_OptionKeyPath)(BSTR bstrOptionKeyPath)
{
m_bstrOptionKeyPath = bstrOptionKeyPath;;
return S_OK;
}
STDMETHOD(get_OptionKeyPath)(BSTR* pbstrOptionKeyPath)
{
*pbstrOptionKeyPath = m_bstrOptionKeyPath;
return S_OK;
}
// IObjectWithSite
STDMETHOD(SetSite)(IUnknown* pUnkSite)
{
HRESULT hr = IObjectWithSiteImpl<CAxHostWindow>::SetSite(pUnkSite);
if (SUCCEEDED(hr) && m_spUnkSite)
{
// Look for "outer" IServiceProvider
hr = m_spUnkSite->QueryInterface(IID_IServiceProvider, (void**)&m_spServices);
ATLASSERT( !hr && "No ServiceProvider!" );
}
if (pUnkSite == NULL)
m_spServices.Release();
return hr;
}
// IOleClientSite
STDMETHOD(SaveObject)()
{
ATLTRACENOTIMPL(_T("IOleClientSite::SaveObject"));
}
STDMETHOD(GetMoniker)(DWORD /*dwAssign*/, DWORD /*dwWhichMoniker*/, IMoniker** /*ppmk*/)
{
ATLTRACENOTIMPL(_T("IOleClientSite::GetMoniker"));
}
STDMETHOD(GetContainer)(IOleContainer** ppContainer)
{
ATLTRACE2(atlTraceHosting, 0, _T("IOleClientSite::GetContainer\n"));
HRESULT hr = E_POINTER;
if (ppContainer)
{
hr = E_NOTIMPL;
(*ppContainer) = NULL;
if (m_spUnkSite)
hr = m_spUnkSite->QueryInterface(IID_IOleContainer, (void**)ppContainer);
if (FAILED(hr))
hr = QueryInterface(IID_IOleContainer, (void**)ppContainer);
}
return hr;
}
STDMETHOD(ShowObject)()
{
ATLTRACE2(atlTraceHosting, 0, _T("IOleClientSite::ShowObject\r\n"));
HDC hdc = CWindowImpl<CAxHostWindow>::GetDC();
if (hdc == NULL)
return E_FAIL;
if (m_spViewObject)
m_spViewObject->Draw(DVASPECT_CONTENT, -1, NULL, NULL, NULL, hdc, (RECTL*)&m_rcPos, (RECTL*)&m_rcPos, NULL, NULL);
CWindowImpl<CAxHostWindow>::ReleaseDC(hdc);
return S_OK;
}
STDMETHOD(OnShowWindow)(BOOL /*fShow*/)
{
ATLTRACENOTIMPL(_T("IOleClientSite::OnShowWindow"));
}
STDMETHOD(RequestNewObjectLayout)()
{
ATLTRACENOTIMPL(_T("IOleClientSite::RequestNewObjectLayout"));
}
// IOleInPlaceSite
STDMETHOD(GetWindow)(HWND* phwnd)
{
*phwnd = m_hWnd;
return S_OK;
}
STDMETHOD(ContextSensitiveHelp)(BOOL /*fEnterMode*/)
{
ATLTRACENOTIMPL(_T("IOleWindow::CanInPlaceActivate"));
}
STDMETHOD(CanInPlaceActivate)()
{
return S_OK;
}
STDMETHOD(OnInPlaceActivate)()
{
m_bInPlaceActive = TRUE;
OleLockRunning(m_spOleObject, TRUE, FALSE);
m_bWindowless = FALSE;
m_spOleObject->QueryInterface(IID_IOleInPlaceObject, (void**) &m_spInPlaceObjectWindowless);
return S_OK;
}
STDMETHOD(OnUIActivate)()
{
ATLTRACE2(atlTraceHosting, 0, _T("IOleInPlaceSite::OnUIActivate\n"));
m_bUIActive = TRUE;
return S_OK;
}
STDMETHOD(GetWindowContext)(IOleInPlaceFrame** ppFrame, IOleInPlaceUIWindow** ppDoc, LPRECT lprcPosRect, LPRECT lprcClipRect, LPOLEINPLACEFRAMEINFO pFrameInfo)
{
HRESULT hr = S_OK;
if (ppFrame == NULL || ppDoc == NULL || lprcPosRect == NULL || lprcClipRect == NULL)
hr = E_POINTER;
ATLASSERT(SUCCEEDED(hr));
if (SUCCEEDED(hr))
{
if (!m_spInPlaceFrame)
{
CComObject<CAxFrameWindow>* pFrameWindow;
CComObject<CAxFrameWindow>::CreateInstance(&pFrameWindow);
pFrameWindow->QueryInterface(IID_IOleInPlaceFrame, (void**) &m_spInPlaceFrame);
ATLASSERT(m_spInPlaceFrame);
}
if (!m_spInPlaceUIWindow)
{
CComObject<CAxUIWindow>* pUIWindow;
CComObject<CAxUIWindow>::CreateInstance(&pUIWindow);
pUIWindow->QueryInterface(IID_IOleInPlaceUIWindow, (void**) &m_spInPlaceUIWindow);
ATLASSERT(m_spInPlaceUIWindow);
}
m_spInPlaceFrame.CopyTo(ppFrame);
m_spInPlaceUIWindow.CopyTo(ppDoc);
GetClientRect(lprcPosRect);
GetClientRect(lprcClipRect);
ACCEL ac = { 0,0,0 };
HACCEL hac = CreateAcceleratorTable(&ac, 1);
pFrameInfo->cb = sizeof(OLEINPLACEFRAMEINFO);
pFrameInfo->fMDIApp = m_bMDIApp;
pFrameInfo->hwndFrame = GetParent();
pFrameInfo->haccel = hac;
pFrameInfo->cAccelEntries = 1;
}
return hr;
}
STDMETHOD(Scroll)(SIZE /*scrollExtant*/)
{
ATLTRACENOTIMPL(_T("IOleInPlaceSite::Scroll"));
}
STDMETHOD(OnUIDeactivate)(BOOL /*fUndoable*/)
{
ATLTRACE2(atlTraceHosting, 0, _T("IOleInPlaceSite::OnUIDeactivate\n"));
m_bUIActive = FALSE;
return S_OK;
}
STDMETHOD(OnInPlaceDeactivate)()
{
m_bInPlaceActive = FALSE;
m_spInPlaceObjectWindowless.Release();
return S_OK;
}
STDMETHOD(DiscardUndoState)()
{
ATLTRACENOTIMPL(_T("IOleInPlaceSite::DiscardUndoState"));
}
STDMETHOD(DeactivateAndUndo)()
{
ATLTRACENOTIMPL(_T("IOleInPlaceSite::DeactivateAndUndo"));
}
STDMETHOD(OnPosRectChange)(LPCRECT /*lprcPosRect*/)
{
ATLTRACENOTIMPL(_T("IOleInPlaceSite::OnPosRectChange"));
}
// IOleInPlaceSiteEx
STDMETHOD(OnInPlaceActivateEx)(BOOL* /*pfNoRedraw*/, DWORD dwFlags)
{
m_bInPlaceActive = TRUE;
OleLockRunning(m_spOleObject, TRUE, FALSE);
HRESULT hr = E_FAIL;
if (dwFlags & ACTIVATE_WINDOWLESS)
{
m_bWindowless = TRUE;
hr = m_spOleObject->QueryInterface(IID_IOleInPlaceObjectWindowless, (void**) &m_spInPlaceObjectWindowless);
}
if (FAILED(hr))
{
m_bWindowless = FALSE;
hr = m_spOleObject->QueryInterface(IID_IOleInPlaceObject, (void**) &m_spInPlaceObjectWindowless);
}
if (m_spInPlaceObjectWindowless)
m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);
return S_OK;
}
STDMETHOD(OnInPlaceDeactivateEx)(BOOL /*fNoRedraw*/)
{
return S_OK;
}
STDMETHOD(RequestUIActivate)()
{
return S_OK;
}
// IOleInPlaceSiteWindowless
STDMETHOD(CanWindowlessActivate)()
{
return m_bCanWindowlessActivate ? S_OK : S_FALSE;
}
STDMETHOD(GetCapture)()
{
return m_bCapture ? S_OK : S_FALSE;
}
STDMETHOD(SetCapture)(BOOL fCapture)
{
if (fCapture)
{
CWindow::SetCapture();
m_bCapture = TRUE;
}
else
{
ReleaseCapture();
m_bCapture = FALSE;
}
return S_OK;
}
STDMETHOD(GetFocus)()
{
return S_OK;
}
STDMETHOD(SetFocus)(BOOL /*fFocus*/)
{
return S_OK;
}
STDMETHOD(GetDC)(LPCRECT /*pRect*/, DWORD /*grfFlags*/, HDC* phDC)
{
if (phDC)
return E_POINTER;
*phDC = CWindowImpl<CAxHostWindow>::GetDC();
return S_OK;
}
STDMETHOD(ReleaseDC)(HDC hDC)
{
CWindowImpl<CAxHostWindow>::ReleaseDC(hDC);
return S_OK;
}
STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase)
{
CWindowImpl<CAxHostWindow>::InvalidateRect(pRect, fErase);
return S_OK;
}
STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase)
{
CWindowImpl<CAxHostWindow>::InvalidateRgn(hRGN, fErase);
return S_OK;
}
STDMETHOD(ScrollRect)(INT /*dx*/, INT /*dy*/, LPCRECT /*pRectScroll*/, LPCRECT /*pRectClip*/)
{
return S_OK;
}
STDMETHOD(AdjustRect)(LPRECT /*prc*/)
{
return S_OK;
}
STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult)
{
*plResult = DefWindowProc(msg, wParam, lParam);
return S_OK;
}
// IOleControlSite
STDMETHOD(OnControlInfoChanged)()
{
return S_OK;
}
STDMETHOD(LockInPlaceActive)(BOOL /*fLock*/)
{
return S_OK;
}
STDMETHOD(GetExtendedControl)(IDispatch** ppDisp)
{
if (ppDisp == NULL)
return E_POINTER;
return m_spOleObject.QueryInterface(ppDisp);
}
STDMETHOD(TransformCoords)(POINTL* /*pPtlHimetric*/, POINTF* /*pPtfContainer*/, DWORD /*dwFlags*/)
{
return S_OK;
}
STDMETHOD(TranslateAccelerator)(LPMSG /*lpMsg*/, DWORD /*grfModifiers*/)
{
return S_FALSE;
}
STDMETHOD(OnFocus)(BOOL /*fGotFocus*/)
{
return S_OK;
}
STDMETHOD(ShowPropertyFrame)()
{
return E_NOTIMPL;
}
// IAdviseSink
STDMETHOD_(void, OnDataChange)(FORMATETC* /*pFormatetc*/, STGMEDIUM* /*pStgmed*/)
{
}
STDMETHOD_(void, OnViewChange)(DWORD /*dwAspect*/, LONG /*lindex*/)
{
}
STDMETHOD_(void, OnRename)(IMoniker* /*pmk*/)
{
}
STDMETHOD_(void, OnSave)()
{
}
STDMETHOD_(void, OnClose)()
{
}
// IOleContainer
STDMETHOD(ParseDisplayName)(IBindCtx* /*pbc*/, LPOLESTR /*pszDisplayName*/, ULONG* /*pchEaten*/, IMoniker** /*ppmkOut*/)
{
return E_NOTIMPL;
}
STDMETHOD(EnumObjects)(DWORD /*grfFlags*/, IEnumUnknown** ppenum)
{
if (ppenum == NULL)
return E_POINTER;
*ppenum = NULL;
typedef CComObject<CComEnum<IEnumUnknown, &IID_IEnumUnknown, IUnknown*, _CopyInterface<IUnknown> > > enumunk;
enumunk* p = NULL;
ATLTRY(p = new enumunk);
if(p == NULL)
return E_OUTOFMEMORY;
HRESULT hRes = p->Init(reinterpret_cast<IUnknown**>(&m_spUnknown), reinterpret_cast<IUnknown**>(&m_spOleObject), GetControllingUnknown(), AtlFlagCopy);
if (SUCCEEDED(hRes))
hRes = p->QueryInterface(IID_IEnumUnknown, (void**)ppenum);
if (FAILED(hRes))
delete p;
return hRes;
}
STDMETHOD(LockContainer)(BOOL fLock)
{
m_bLocked = fLock;
return S_OK;
}
HRESULT ActivateAx(IUnknown* pUnkControl, bool bInited, IStream* pStream)
{
if (pUnkControl == NULL)
return S_OK;
m_spUnknown = pUnkControl;
HRESULT hr = S_OK;
pUnkControl->QueryInterface(IID_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<IPersistStreamInit, &IID_IPersistStreamInit> spPSI(m_spOleObject);
if (!bInited && spPSI)
{
if (pStream)
spPSI->Load(pStream);
else
spPSI->InitNew();
}
if(0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST))
{
CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());
m_spOleObject->SetClientSite(spClientSite);
}
m_dwViewObjectType = 0;
HRESULT hr;
hr = m_spOleObject->QueryInterface(IID_IViewObjectEx, (void**) &m_spViewObject);
if (FAILED(hr))
{
hr = m_spOleObject->QueryInterface(IID_IViewObject2, (void**) &m_spViewObject);
m_dwViewObjectType = 3;
} else
m_dwViewObjectType = 7;
if (FAILED(hr))
{
hr = m_spOleObject->QueryInterface(IID_IViewObject, (void**) &m_spViewObject);
m_dwViewObjectType = 1;
}
CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());
m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);
if (m_dwViewObjectType)
m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);
m_spOleObject->SetHostNames(OLESTR("AXWIN"), NULL);
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(IID_IObjectWithSite, (void**)&spSite);
if (spSite != NULL)
spSite->SetSite(GetControllingUnknown());
return hr;
}
// pointers
CComPtr<IUnknown> m_spUnknown;
CComPtr<IOleObject> m_spOleObject;
CComPtr<IOleInPlaceFrame> m_spInPlaceFrame;
CComPtr<IOleInPlaceUIWindow> m_spInPlaceUIWindow;
CComPtr<IViewObjectEx> m_spViewObject;
CComPtr<IOleInPlaceObjectWindowless> m_spInPlaceObjectWindowless;
CComPtr<IDispatch> m_spExternalDispatch;
#ifndef _ATL_NO_DOCHOSTUIHANDLER
CComPtr<IDocHostUIHandlerDispatch> m_spIDocHostUIHandlerDispatch;
#endif
IID m_iidSink;
DWORD m_dwViewObjectType;
DWORD m_dwAdviseSink;
// state
unsigned long m_bInPlaceActive:1;
unsigned long m_bUIActive:1;
unsigned long m_bMDIApp:1;
unsigned long m_bWindowless:1;
unsigned long m_bCapture:1;
unsigned long m_bHaveFocus:1;
unsigned long m_bReleaseAll:1;
unsigned long m_bLocked:1;
DWORD m_dwOleObject;
DWORD m_dwMiscStatus;
SIZEL m_hmSize;
SIZEL m_pxSize;
RECT m_rcPos;
// Ambient property storage
unsigned long m_bCanWindowlessActivate:1;
unsigned long m_bUserMode:1;
unsigned long m_bDisplayAsDefault:1;
unsigned long m_bMessageReflect:1;
unsigned long m_bSubclassed:1;
unsigned long m_bAllowContextMenu:1;
unsigned long m_bAllowShowUI:1;
OLE_COLOR m_clrBackground;
OLE_COLOR m_clrForeground;
LCID m_lcidLocaleID;
CComPtr<IFontDisp> m_spFont;
CComPtr<IServiceProvider> m_spServices;
DWORD m_dwDocHostFlags;
DWORD m_dwDocHostDoubleClickFlags;
CComBSTR m_bstrOptionKeyPath;
void SubclassWindow(HWND hWnd)
{
m_bSubclassed = CWindowImpl<CAxHostWindow>::SubclassWindow(hWnd);
}
void ReleaseWindow()
{
if (m_bSubclassed)
{
if(UnsubclassWindow(TRUE) != NULL)
m_bSubclassed = FALSE;
}
else
DestroyWindow();
}
// Reflection
LRESULT ReflectNotifications(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
HWND hWndChild = NULL;
switch(uMsg)
{
case WM_COMMAND:
if(lParam != NULL) // not from a menu
hWndChild = (HWND)lParam;
break;
case WM_NOTIFY:
hWndChild = ((LPNMHDR)lParam)->hwndFrom;
break;
case WM_PARENTNOTIFY:
switch(LOWORD(wParam))
{
case WM_CREATE:
case WM_DESTROY:
hWndChild = (HWND)lParam;
break;
default:
hWndChild = GetDlgItem(HIWORD(wParam));
break;
}
break;
case WM_DRAWITEM:
if(wParam) // not from a menu
hWndChild = ((LPDRAWITEMSTRUCT)lParam)->hwndItem;
break;
case WM_MEASUREITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPMEASUREITEMSTRUCT)lParam)->CtlID);
break;
case WM_COMPAREITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPCOMPAREITEMSTRUCT)lParam)->CtlID);
break;
case WM_DELETEITEM:
if(wParam) // not from a menu
hWndChild = GetDlgItem(((LPDELETEITEMSTRUCT)lParam)->CtlID);
break;
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
case WM_HSCROLL:
case WM_VSCROLL:
hWndChild = (HWND)lParam;
break;
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLORSCROLLBAR:
case WM_CTLCOLORSTATIC:
hWndChild = (HWND)lParam;
break;
default:
break;
}
if(hWndChild == NULL)
{
bHandled = FALSE;
return 1;
}
ATLASSERT(::IsWindow(hWndChild));
return ::SendMessage(hWndChild, OCM__BASE + uMsg, wParam, lParam);
}
STDMETHOD(QueryService)( REFGUID rsid, REFIID riid, void** ppvObj)
{
HRESULT hr = E_NOINTERFACE;
// Try for service on this object
// No services currently
// If that failed try to find the service on the outer object
if (FAILED(hr) && m_spServices)
hr = m_spServices->QueryService(rsid, riid, ppvObj);
return hr;
}
};
/////////////////////////////////////////////////////////////////////////////
// Helper functions for cracking dialog templates
#define _ATL_RT_DLGINIT MAKEINTRESOURCE(240)
class _DialogSplitHelper
{
public:
// Constants used in DLGINIT resources for OLE control containers
// NOTE: These are NOT real Windows messages they are simply tags
// used in the control resource and are never used as 'messages'
enum
{
WM_OCC_LOADFROMSTREAM = 0x0376,
WM_OCC_LOADFROMSTORAGE = 0x0377,
WM_OCC_INITNEW = 0x0378,
WM_OCC_LOADFROMSTREAM_EX = 0x037A,
WM_OCC_LOADFROMSTORAGE_EX = 0x037B,
DISPID_DATASOURCE = 0x80010001,
DISPID_DATAFIELD = 0x80010002,
};
//local struct used for implementation
#pragma pack(push, 1)
struct DLGINITSTRUCT
{
WORD nIDC;
WORD message;
DWORD dwSize;
};
struct DLGTEMPLATEEX
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
// Everything else in this structure is variable length,
// and therefore must be determined dynamically
// sz_Or_Ord menu; // name or ordinal of a menu resource
// sz_Or_Ord windowClass; // name or ordinal of a window class
// WCHAR title[titleLen]; // title string of the dialog box
// short pointsize; // only if DS_SETFONT is set
// short weight; // only if DS_SETFONT is set
// short bItalic; // only if DS_SETFONT is set
// WCHAR font[fontLen]; // typeface name, if DS_SETFONT is set
};
struct DLGITEMTEMPLATEEX
{
DWORD helpID;
DWORD exStyle;
DWORD style;
short x;
short y;
short cx;
short cy;
DWORD id;
// Everything else in this structure is variable length,
// and therefore must be determined dynamically
// sz_Or_Ord windowClass; // name or ordinal of a window class
// sz_Or_Ord title; // title string or ordinal of a resource
// WORD extraCount; // bytes following creation data
};
#pragma pack(pop)
static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
{
return ((DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
}
inline static WORD& DlgTemplateItemCount(DLGTEMPLATE* pTemplate)
{
if (IsDialogEx(pTemplate))
return reinterpret_cast<DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
else
return pTemplate->cdit;
}
inline static const WORD& DlgTemplateItemCount(const DLGTEMPLATE* pTemplate)
{
if (IsDialogEx(pTemplate))
return reinterpret_cast<const DLGTEMPLATEEX*>(pTemplate)->cDlgItems;
else
return pTemplate->cdit;
}
static DLGITEMTEMPLATE* FindFirstDlgItem(const DLGTEMPLATE* pTemplate)
{
BOOL bDialogEx = IsDialogEx(pTemplate);
WORD* pw;
DWORD dwStyle;
if (bDialogEx)
{
pw = (WORD*)((DLGTEMPLATEEX*)pTemplate + 1);
dwStyle = ((DLGTEMPLATEEX*)pTemplate)->style;
}
else
{
pw = (WORD*)(pTemplate + 1);
dwStyle = pTemplate->style;
}
// Check for presence of menu and skip it if there is one
// 0x0000 means there is no menu
// 0xFFFF means there is a menu ID following
// Everything else means that this is a NULL terminated Unicode string
// which identifies the menu resource
if (*pw == 0xFFFF)
pw += 2; // Has menu ID, so skip 2 words
else
while (*pw++); // Either No menu, or string, skip past terminating NULL
// Check for presence of class name string
// 0x0000 means "Use system dialog class name"
// 0xFFFF means there is a window class (atom) specified
// Everything else means that this is a NULL terminated Unicode string
// which identifies the menu resource
if (*pw == 0xFFFF)
pw += 2; // Has class atom, so skip 2 words
else
while (*pw++); // Either No class, or string, skip past terminating NULL
// Skip caption string
while (*pw++);
// If we have DS_SETFONT, there is extra font information which we must now skip
if (dwStyle & DS_SETFONT)
{
// If it is a regular DLGTEMPLATE there is only a short for the point size
// and a string specifying the font (typefacename). If this is a DLGTEMPLATEEX
// then there is also the font weight, and bItalic which must be skipped
if (bDialogEx)
pw += 3; // Skip font size, weight, (italic, charset)
else
pw += 1; // Skip font size
while (*pw++); // Skip typeface name
}
// Dword-align and return
return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + 3) & ~DWORD_PTR(3));
}
// Given the current dialog item and whether this is an extended dialog
// return a pointer to the next DLGITEMTEMPLATE*
static DLGITEMTEMPLATE* FindNextDlgItem(DLGITEMTEMPLATE* pItem, BOOL bDialogEx)
{
WORD* pw;
// First skip fixed size header information, size of which depends
// if this is a DLGITEMTEMPLATE or DLGITEMTEMPLATEEX
if (bDialogEx)
pw = (WORD*)((DLGITEMTEMPLATEEX*)pItem + 1);
else
pw = (WORD*)(pItem + 1);
if (*pw == 0xFFFF) // Skip class name ordinal or string
pw += 2; // (WORDs)
else
while (*pw++);
if (*pw == 0xFFFF) // Skip title ordinal or string
pw += 2; // (WORDs)
else
while (*pw++);
WORD cbExtra = *pw++; // Skip extra data
// Dword-align and return
return (DLGITEMTEMPLATE*)(((DWORD_PTR)pw + cbExtra + 3) & ~DWORD_PTR(3));
}
// Find the initialization data (Stream) for the control specified by the ID
// If found, return the pointer into the data and the length of the data
static DWORD FindCreateData(DWORD dwID, BYTE* pInitData, BYTE** pData)
{
while (pInitData)
{
// Read the DLGINIT header
WORD nIDC = *((UNALIGNED WORD*)pInitData);
pInitData += sizeof(WORD);
WORD nMsg = *((UNALIGNED WORD*)pInitData);
pInitData += sizeof(WORD);
DWORD dwLen = *((UNALIGNED DWORD*)pInitData);
pInitData += sizeof(DWORD);
// If the header is for the control specified get the other info
if (nIDC == dwID)
{
DWORD cchLicKey = *((UNALIGNED DWORD*)pInitData);
pInitData += sizeof(DWORD);
dwLen -= sizeof(DWORD);
if (cchLicKey > 0)
{
CComBSTR bstrLicKey;
bstrLicKey.m_str = SysAllocStringLen((LPCOLESTR)pInitData, cchLicKey);
pInitData += cchLicKey * sizeof(OLECHAR);
dwLen -= cchLicKey * sizeof(OLECHAR);
}
// Extended (DATABINDING) stream format is not supported,
// we reject databinding info but preserve other information
if (nMsg == WM_OCC_LOADFROMSTREAM_EX ||
nMsg == WM_OCC_LOADFROMSTORAGE_EX)
{
// Read the size of the section
ULONG cbOffset = *(UNALIGNED ULONG*)pInitData;
// and simply skip past it
*pData = pInitData + cbOffset;
dwLen = dwLen - cbOffset;
return dwLen;
}
if (nMsg == WM_OCC_LOADFROMSTREAM)
*pData = pInitData;
return dwLen;
}
// It's not the right control, skip past data
pInitData += dwLen;
}
return 0;
}
// Convert MSDEV (MFC) style DLGTEMPLATE with controls to regular DLGTEMPLATE
// Changing all ActiveX Controls to use ATL AxWin hosting code
static DLGTEMPLATE* SplitDialogTemplate(DLGTEMPLATE* pTemplate, BYTE* pInitData)
{
USES_CONVERSION;
LPCWSTR lpstrAxWndClassNameW = T2CW(CAxWindow::GetWndClassName());
// Calculate the size of the DLGTEMPLATE for allocating the new one
DLGITEMTEMPLATE* pFirstItem = FindFirstDlgItem(pTemplate);
ULONG cbHeader = ULONG((BYTE*)pFirstItem - (BYTE*)pTemplate);
ULONG cbNewTemplate = cbHeader;
BOOL bDialogEx = IsDialogEx(pTemplate);
int iItem;
int nItems = (int)DlgTemplateItemCount(pTemplate);
#ifndef OLE2ANSI
LPWSTR pszClassName;
#else
LPSTR pszClassName;
#endif
BOOL bHasOleControls = FALSE;
// Make first pass through the dialog template. On this pass, we're
// interested in determining:
// 1. Does this template contain any ActiveX Controls?
// 2. If so, how large a buffer is needed for a template containing
// only the non-OLE controls?
DLGITEMTEMPLATE* pItem = pFirstItem;
DLGITEMTEMPLATE* pNextItem = pItem;
for (iItem = 0; iItem < nItems; iItem++)
{
pNextItem = FindNextDlgItem(pItem, bDialogEx);
pszClassName = bDialogEx ?
#ifndef OLE2ANSI
(LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
(LPWSTR)(pItem + 1);
#else
(LPSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
(LPSTR)(pItem + 1);
#endif
// Check if the class name begins with a '{'
// If it does, that means it is an ActiveX Control in MSDEV (MFC) format
#ifndef OLE2ANSI
if (pszClassName[0] == L'{')
#else
if (pszClassName[0] == '{')
#endif
{
// Item is an ActiveX control.
bHasOleControls = TRUE;
cbNewTemplate += (ULONG)((bDialogEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE)));
// Length of className including NULL terminator
cbNewTemplate += (lstrlenW(lpstrAxWndClassNameW) + 1) * sizeof(WCHAR);
// Add length for the title CLSID in the form "{00000010-0000-0010-8000-00AA006D2EA4}"
// plus room for terminating NULL and an extra WORD for cbExtra
cbNewTemplate += 80;
// Get the Control ID
DWORD wID = bDialogEx ? ((DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
BYTE* pData;
cbNewTemplate += FindCreateData(wID, pInitData, &pData);
// Align to next DWORD
cbNewTemplate = ((cbNewTemplate + 3) & ~3);
}
else
{
// Item is not an ActiveX Control: make room for it in new template.
cbNewTemplate += ULONG((BYTE*)pNextItem - (BYTE*)pItem);
}
pItem = pNextItem;
}
// No OLE controls were found, so there's no reason to go any further.
if (!bHasOleControls)
return pTemplate;
// Copy entire header into new template.
BYTE* pNew = (BYTE*)GlobalAlloc(GMEM_FIXED, cbNewTemplate);
DLGTEMPLATE* pNewTemplate = (DLGTEMPLATE*)pNew;
memcpy(pNew, pTemplate, cbHeader);
pNew += cbHeader;
// Initialize item count in new header to zero.
DlgTemplateItemCount(pNewTemplate) = 0;
pItem = pFirstItem;
pNextItem = pItem;
// Second pass through the dialog template. On this pass, we want to:
// 1. Copy all the non-OLE controls into the new template.
// 2. Build an array of item templates for the OLE controls.
for (iItem = 0; iItem < nItems; iItem++)
{
pNextItem = FindNextDlgItem(pItem, bDialogEx);
pszClassName = bDialogEx ?
#ifndef OLE2ANSI
(LPWSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
(LPWSTR)(pItem + 1);
if (pszClassName[0] == L'{')
#else
(LPSTR)(((DLGITEMTEMPLATEEX*)pItem) + 1) :
(LPSTR)(pItem + 1);
if (pszClassName[0] == '{')
#endif
{
// Item is OLE control: add it to template as custom control
// Copy the dialog item template
DWORD nSizeElement = (DWORD)(bDialogEx ? sizeof(DLGITEMTEMPLATEEX) : sizeof(DLGITEMTEMPLATE));
memcpy(pNew, pItem, nSizeElement);
pNew += nSizeElement;
// Copy ClassName
DWORD nClassName = (lstrlenW(lpstrAxWndClassNameW) + 1) * sizeof(WCHAR);
memcpy(pNew, lpstrAxWndClassNameW, nClassName);
pNew += nClassName;
// Title (CLSID)
memcpy(pNew, pszClassName, 78);
pNew += 78; // sizeof(L"{00000010-0000-0010-8000-00AA006D2EA4}") - A CLSID
DWORD wID = bDialogEx ? ((DLGITEMTEMPLATEEX*)pItem)->id : pItem->id;
BYTE* pData;
nSizeElement = FindCreateData(wID, pInitData, &pData);
// cbExtra
*((WORD*)pNew) = (WORD) nSizeElement;
pNew += sizeof(WORD);
memcpy(pNew, pData, nSizeElement);
pNew += nSizeElement;
//Align to DWORD
pNew += (((~((DWORD_PTR)pNew)) + 1) & 3);
// Incrememt item count in new header.
++DlgTemplateItemCount(pNewTemplate);
}
else
{
// Item is not an OLE control: copy it to the new template.
ULONG cbItem = ULONG((BYTE*)pNextItem - (BYTE*)pItem);
ATLASSERT(cbItem >= (size_t)(bDialogEx ?
sizeof(DLGITEMTEMPLATEEX) :
sizeof(DLGITEMTEMPLATE)));
memcpy(pNew, pItem, cbItem);
pNew += cbItem;
// Incrememt item count in new header.
++DlgTemplateItemCount(pNewTemplate);
}
pItem = pNextItem;
}
//ppOleDlgItems[nItems] = (DLGITEMTEMPLATE*)(-1);
return pNewTemplate;
}
};
static LRESULT CALLBACK AtlAxWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_CREATE:
{
// create control from a PROGID in the title
// This is to make sure drag drop works
::OleInitialize(NULL);
CREATESTRUCT* lpCreate = (CREATESTRUCT*)lParam;
int nLen = ::GetWindowTextLength(hWnd);
LPTSTR lpstrName = (LPTSTR)_alloca((nLen + 1) * sizeof(TCHAR));
::GetWindowText(hWnd, lpstrName, nLen + 1);
::SetWindowText(hWnd, _T(""));
IAxWinHostWindow* pAxWindow = NULL;
int nCreateSize = 0;
if (lpCreate && lpCreate->lpCreateParams)
nCreateSize = *((WORD*)lpCreate->lpCreateParams);
HGLOBAL h = GlobalAlloc(GHND, nCreateSize);
CComPtr<IStream> spStream;
if (h && nCreateSize)
{
BYTE* pBytes = (BYTE*) GlobalLock(h);
BYTE* pSource = ((BYTE*)(lpCreate->lpCreateParams)) + sizeof(WORD);
//Align to DWORD
//pSource += (((~((DWORD)pSource)) + 1) & 3);
memcpy(pBytes, pSource, nCreateSize);
GlobalUnlock(h);
CreateStreamOnHGlobal(h, TRUE, &spStream);
}
USES_CONVERSION;
CComPtr<IUnknown> spUnk;
HRESULT hRet = AtlAxCreateControl(T2COLE(lpstrName), hWnd, spStream, &spUnk);
if(FAILED(hRet))
return -1; // abort window creation
hRet = spUnk->QueryInterface(IID_IAxWinHostWindow, (void**)&pAxWindow);
if(FAILED(hRet))
return -1; // abort window creation
::SetWindowLongPtr(hWnd, GWLP_USERDATA, (LPARAM)pAxWindow);
// check for control parent style if control has a window
HWND hWndChild = ::GetWindow(hWnd, GW_CHILD);
if(hWndChild != NULL)
{
if(::GetWindowLong(hWndChild, GWL_EXSTYLE) & WS_EX_CONTROLPARENT)
{
DWORD dwExStyle = ::GetWindowLong(hWnd, GWL_EXSTYLE);
dwExStyle |= WS_EX_CONTROLPARENT;
::SetWindowLong(hWnd, GWL_EXSTYLE, dwExStyle);
}
}
// continue with DefWindowProc
}
break;
case WM_NCDESTROY:
{
IAxWinHostWindow* pAxWindow = (IAxWinHostWindow*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
if(pAxWindow != NULL)
pAxWindow->Release();
OleUninitialize();
}
break;
default:
break;
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
}; //namespace ATL
#ifndef _ATL_DLL_IMPL
#ifndef _ATL_DLL
#define _ATLHOST_IMPL
#endif
#endif
#ifdef _ATLHOST_IMPL
#ifndef _ATL_DLL_IMPL
namespace ATL
{
#endif
//All exports go here
ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam)
{
AtlAxWinInit();
HRSRC hDlg = ::FindResourceW(hInstance, lpTemplateName, (LPWSTR)RT_DIALOG);
HRSRC hDlgInit = ::FindResourceW(hInstance, lpTemplateName, (LPWSTR)_ATL_RT_DLGINIT);
HGLOBAL hData = NULL;
BYTE* pInitData = NULL;
INT_PTR nRet = -1;
if (hDlgInit)
{
hData = ::LoadResource(hInstance, hDlgInit);
pInitData = (BYTE*) ::LockResource(hData);
}
if (hDlg)
{
HGLOBAL hResource = LoadResource(hInstance, hDlg);
DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource);
LPCDLGTEMPLATE lpDialogTemplate;
lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
nRet = ::DialogBoxIndirectParamW(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam);
if (lpDialogTemplate != pDlg)
GlobalFree(GlobalHandle(lpDialogTemplate));
UnlockResource(hResource);
FreeResource(hResource);
}
if (pInitData && hDlgInit)
{
UnlockResource(hData);
FreeResource(hData);
}
return nRet;
}
ATLINLINE ATLAPI_(INT_PTR) AtlAxDialogBoxA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam)
{
AtlAxWinInit();
HRSRC hDlg = ::FindResourceA(hInstance, lpTemplateName, (LPSTR)RT_DIALOG);
HRSRC hDlgInit = ::FindResourceA(hInstance, lpTemplateName, (LPSTR)_ATL_RT_DLGINIT);
HGLOBAL hData = NULL;
BYTE* pInitData = NULL;
INT_PTR nRet = -1;
if (hDlgInit)
{
hData = ::LoadResource(hInstance, hDlgInit);
pInitData = (BYTE*) ::LockResource(hData);
}
if (hDlg)
{
HGLOBAL hResource = LoadResource(hInstance, hDlg);
DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource);
LPCDLGTEMPLATE lpDialogTemplate;
lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
nRet = ::DialogBoxIndirectParamA(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam);
if (lpDialogTemplate != pDlg)
GlobalFree(GlobalHandle(lpDialogTemplate));
UnlockResource(hResource);
FreeResource(hResource);
}
if (pInitData && hDlgInit)
{
UnlockResource(hData);
FreeResource(hData);
}
return nRet;
}
ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogW(HINSTANCE hInstance, LPCWSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam)
{
AtlAxWinInit();
HRSRC hDlg = ::FindResourceW(hInstance, lpTemplateName, (LPWSTR)RT_DIALOG);
HRSRC hDlgInit = ::FindResourceW(hInstance, lpTemplateName, (LPWSTR)_ATL_RT_DLGINIT);
HGLOBAL hData = NULL;
BYTE* pInitData = NULL;
HWND hWnd = NULL;
if (hDlgInit)
{
hData = ::LoadResource(hInstance, hDlgInit);
pInitData = (BYTE*) ::LockResource(hData);
}
if (hDlg)
{
HGLOBAL hResource = LoadResource(hInstance, hDlg);
DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource);
LPCDLGTEMPLATE lpDialogTemplate;
lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
hWnd = ::CreateDialogIndirectParamW(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam);
if (lpDialogTemplate != pDlg)
GlobalFree(GlobalHandle(lpDialogTemplate));
UnlockResource(hResource);
FreeResource(hResource);
}
if (pInitData && hDlgInit)
{
UnlockResource(hData);
FreeResource(hData);
}
return hWnd;
}
ATLINLINE ATLAPI_(HWND) AtlAxCreateDialogA(HINSTANCE hInstance, LPCSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogProc, LPARAM dwInitParam)
{
AtlAxWinInit();
HRSRC hDlg = ::FindResourceA(hInstance, lpTemplateName, (LPSTR)RT_DIALOG);
HRSRC hDlgInit = ::FindResourceA(hInstance, lpTemplateName, (LPSTR)_ATL_RT_DLGINIT);
HGLOBAL hData = NULL;
BYTE* pInitData = NULL;
HWND hWnd = NULL;
if (hDlgInit)
{
hData = ::LoadResource(hInstance, hDlgInit);
pInitData = (BYTE*) ::LockResource(hData);
}
if (hDlg)
{
HGLOBAL hResource = LoadResource(hInstance, hDlg);
DLGTEMPLATE* pDlg = (DLGTEMPLATE*) LockResource(hResource);
LPCDLGTEMPLATE lpDialogTemplate;
lpDialogTemplate = _DialogSplitHelper::SplitDialogTemplate(pDlg, pInitData);
hWnd = ::CreateDialogIndirectParamA(hInstance, lpDialogTemplate, hWndParent, lpDialogProc, dwInitParam);
if (lpDialogTemplate != pDlg)
GlobalFree(GlobalHandle(lpDialogTemplate));
UnlockResource(hResource);
FreeResource(hResource);
}
if (pInitData && hDlgInit)
{
UnlockResource(hData);
FreeResource(hData);
}
return hWnd;
}
ATLINLINE ATLAPI AtlAxCreateControl(LPCOLESTR lpszName, HWND hWnd, IStream* pStream, IUnknown** ppUnkContainer)
{
return AtlAxCreateControlEx(lpszName, hWnd, pStream, ppUnkContainer, NULL, IID_NULL, NULL);
}
ATLINLINE ATLAPI AtlAxCreateControlEx(LPCOLESTR lpszName, HWND hWnd, IStream* pStream,
IUnknown** ppUnkContainer, IUnknown** ppUnkControl, REFIID iidSink, IUnknown* punkSink)
{
AtlAxWinInit();
HRESULT hr;
CComPtr<IUnknown> spUnkContainer;
CComPtr<IUnknown> spUnkControl;
hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, IID_IUnknown, (void**)&spUnkContainer);
if (SUCCEEDED(hr))
{
CComPtr<IAxWinHostWindow> pAxWindow;
spUnkContainer->QueryInterface(IID_IAxWinHostWindow, (void**)&pAxWindow);
CComBSTR bstrName(lpszName);
hr = pAxWindow->CreateControlEx(bstrName, hWnd, pStream, &spUnkControl, iidSink, punkSink);
}
if (ppUnkContainer != NULL)
{
if (SUCCEEDED(hr))
{
*ppUnkContainer = spUnkContainer.p;
spUnkContainer.p = NULL;
}
else
*ppUnkContainer = NULL;
}
if (ppUnkControl != NULL)
{
if (SUCCEEDED(hr))
{
*ppUnkControl = SUCCEEDED(hr) ? spUnkControl.p : NULL;
spUnkControl.p = NULL;
}
else
*ppUnkControl = NULL;
}
return hr;
}
ATLINLINE ATLAPI AtlAxAttachControl(IUnknown* pControl, HWND hWnd, IUnknown** ppUnkContainer)
{
AtlAxWinInit();
HRESULT hr;
if (pControl == NULL)
return E_INVALIDARG;
CComPtr<IUnknown> spUnkContainer;
hr = CAxHostWindow::_CreatorClass::CreateInstance(NULL, IID_IUnknown, (void**)&spUnkContainer);
if (SUCCEEDED(hr))
{
CComPtr<IAxWinHostWindow> pAxWindow;
spUnkContainer->QueryInterface(IID_IAxWinHostWindow, (void**)&pAxWindow);
hr = pAxWindow->AttachControl(pControl, hWnd);
}
if (ppUnkContainer != NULL)
{
*ppUnkContainer = SUCCEEDED(hr) ? spUnkContainer.p : NULL;
spUnkContainer.p = NULL;
}
return hr;
}
//This either registers a global class (if AtlAxWinInit is in ATL.DLL)
// or it registers a local class
ATLINLINE ATLAPI_(BOOL) AtlAxWinInit()
{
EnterCriticalSection(&_Module.m_csWindowCreate);
WM_ATLGETHOST = RegisterWindowMessage(_T("WM_ATLGETHOST"));
WM_ATLGETCONTROL = RegisterWindowMessage(_T("WM_ATLGETCONTROL"));
WNDCLASSEX wc;
// first check if the class is already registered
wc.cbSize = sizeof(WNDCLASSEX);
BOOL bRet = ::GetClassInfoEx(_Module.GetModuleInstance(), CAxWindow::GetWndClassName(), &wc);
// register class if not
if(!bRet)
{
wc.cbSize = sizeof(WNDCLASSEX);
#ifdef _ATL_DLL_IMPL
wc.style = CS_GLOBALCLASS;
#else
wc.style = 0;
#endif
wc.lpfnWndProc = AtlAxWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = _Module.GetModuleInstance();
wc.hIcon = NULL;
wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = CAxWindow::GetWndClassName();
wc.hIconSm = NULL;
bRet = (BOOL)::RegisterClassEx(&wc);
}
LeaveCriticalSection(&_Module.m_csWindowCreate);
return bRet;
}
ATLINLINE ATLAPI AtlAxGetControl(HWND h, IUnknown** pp)
{
ATLASSERT(WM_ATLGETCONTROL != 0);
if (pp == NULL)
return E_POINTER;
*pp = (IUnknown*)SendMessage(h, WM_ATLGETCONTROL, 0, 0);
return (*pp) ? S_OK : E_FAIL;
}
ATLINLINE ATLAPI AtlAxGetHost(HWND h, IUnknown** pp)
{
ATLASSERT(WM_ATLGETHOST != 0);
if (pp == NULL)
return E_POINTER;
*pp = (IUnknown*)SendMessage(h, WM_ATLGETHOST, 0, 0);
return (*pp) ? S_OK : E_FAIL;
}
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
//Prevent pulling in second time
#undef _ATLHOST_IMPL
#endif // _ATLHOST_IMPL
#endif // __ATLHOST_H__