windows-nt/Source/XPSP1/NT/multimedia/dshow/vidctl/atl/atlctl.h

3401 lines
92 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
// 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 __ATLCTL_H__
#define __ATLCTL_H__
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#include <atlwin.h>
#include <objsafe.h>
#include <urlmon.h>
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "urlmon.lib")
#define DECLARE_VIEW_STATUS(statusFlags) \
DWORD _GetViewStatus() \
{ \
return statusFlags; \
}
// Include GUIDs for the new stock property dialogs contained in the dll MSStkProp.DLL
#include "msstkppg.h"
#include "atliface.h"
#define CLSID_MSStockFont CLSID_StockFontPage
#define CLSID_MSStockColor CLSID_StockColorPage
#define CLSID_MSStockPicture CLSID_StockPicturePage
struct ATL_DRAWINFO
{
UINT cbSize;
DWORD dwDrawAspect;
LONG lindex;
DVTARGETDEVICE* ptd;
HDC hicTargetDev;
HDC hdcDraw;
LPCRECTL prcBounds; //Rectangle in which to draw
LPCRECTL prcWBounds; //WindowOrg and Ext if metafile
BOOL bOptimize;
BOOL bZoomed;
BOOL bRectInHimetric;
SIZEL ZoomNum; //ZoomX = ZoomNum.cx/ZoomNum.cy
SIZEL ZoomDen;
};
namespace ATL
{
#pragma pack(push, _ATL_PACKING)
// Forward declarations
//
class ATL_NO_VTABLE CComControlBase;
template <class T, class WinBase> class CComControl;
//////////////////////////////////////////////////////////////////////////////
// CFirePropNotifyEvent
// Helper functions for safely communicating with objects who sink IPropertyNotifySink
class CFirePropNotifyEvent
{
public:
// Ask any objects sinking the IPropertyNotifySink notification if it is ok to edit a specified property
static HRESULT FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
{
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
if (!pCPC)
return S_OK;
CComPtr<IConnectionPoint> pCP;
pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
if (!pCP)
return S_OK;
CComPtr<IEnumConnections> pEnum;
if (FAILED(pCP->EnumConnections(&pEnum)))
return S_OK;
CONNECTDATA cd;
while (pEnum->Next(1, &cd, NULL) == S_OK)
{
if (cd.pUnk)
{
HRESULT hr = S_OK;
CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
if (pSink)
hr = pSink->OnRequestEdit(dispID);
cd.pUnk->Release();
if (hr == S_FALSE)
return S_FALSE;
}
}
return S_OK;
}
// Notify any objects sinking the IPropertyNotifySink notification that a property has changed
static HRESULT FireOnChanged(IUnknown* pUnk, DISPID dispID)
{
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
if (!pCPC)
return S_OK;
CComPtr<IConnectionPoint> pCP;
pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
if (!pCP)
return S_OK;
CComPtr<IEnumConnections> pEnum;
if (FAILED(pCP->EnumConnections(&pEnum)))
return S_OK;
CONNECTDATA cd;
while (pEnum->Next(1, &cd, NULL) == S_OK)
{
if (cd.pUnk)
{
CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
if (pSink)
pSink->OnChanged(dispID);
cd.pUnk->Release();
}
}
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// CComControlBase
// Holds the essential data members for an ActiveX control and useful helper functions
class ATL_NO_VTABLE CComControlBase
{
public:
CComControlBase(HWND& h) : m_hWndCD(h)
{
memset(this, 0, sizeof(CComControlBase));
m_phWndCD = &h;
m_sizeExtent.cx = 2*2540;
m_sizeExtent.cy = 2*2540;
m_sizeNatural = m_sizeExtent;
}
~CComControlBase()
{
if (m_hWndCD != NULL)
::DestroyWindow(m_hWndCD);
ATLTRACE2(atlTraceControls,2,_T("Control Destroyed\n"));
}
// methods
public:
// Control helper functions can go here non-virtuals only please
// Mark the control 'dirty' so the container will save it
void SetDirty(BOOL bDirty)
{
m_bRequiresSave = bDirty;
}
// Obtain the dirty state for the control
BOOL GetDirty()
{
return m_bRequiresSave ? TRUE : FALSE;
}
// Get the zoom factor (numerator & denominator) which is factor of the natural extent
void GetZoomInfo(ATL_DRAWINFO& di);
// Sends a notification that the moniker for the control has changed
HRESULT SendOnRename(IMoniker *pmk)
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnRename(pmk);
return hRes;
}
// Sends a notification that the control has just saved its data
HRESULT SendOnSave()
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnSave();
return hRes;
}
// Sends a notification that the control has closed its advisory sinks
HRESULT SendOnClose()
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnClose();
return hRes;
}
// Sends a notification that the control's data has changed
HRESULT SendOnDataChange(DWORD advf = 0);
// Sends a notification that the control's representation has changed
HRESULT SendOnViewChange(DWORD dwAspect, LONG lindex = -1)
{
if (m_spAdviseSink)
m_spAdviseSink->OnViewChange(dwAspect, lindex);
return S_OK;
}
// Sends a notification to the container that the control has received focus
LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if (m_bInPlaceActive)
{
CComPtr<IOleObject> pOleObject;
ControlQueryInterface(IID_IOleObject, (void**)&pOleObject);
if (pOleObject != NULL)
pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_spClientSite, 0, m_hWndCD, &m_rcPos);
CComQIPtr<IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
if (m_bInPlaceActive && spSite != NULL)
spSite->OnFocus(TRUE);
}
bHandled = FALSE;
return 1;
}
LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
CComQIPtr<IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
if (m_bInPlaceActive && spSite != NULL && !::IsChild(m_hWndCD, ::GetFocus()))
spSite->OnFocus(FALSE);
bHandled = FALSE;
return 1;
}
LRESULT OnMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
BOOL bUserMode = TRUE;
HRESULT hRet = GetAmbientUserMode(bUserMode);
// UI activate if in user mode only
// allow activation if we can't determine mode
if (FAILED(hRet) || bUserMode)
{
CComPtr<IOleObject> pOleObject;
ControlQueryInterface(IID_IOleObject, (void**)&pOleObject);
if (pOleObject != NULL)
pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_spClientSite, 0, m_hWndCD, &m_rcPos);
}
bHandled = FALSE;
return 1;
}
BOOL PreTranslateAccelerator(LPMSG /*pMsg*/, HRESULT& /*hRet*/)
{
return FALSE;
}
HRESULT GetAmbientProperty(DISPID dispid, VARIANT& var)
{
HRESULT hRes = E_FAIL;
if (m_spAmbientDispatch.p != NULL)
hRes = m_spAmbientDispatch.GetProperty(dispid, &var);
return hRes;
}
HRESULT GetAmbientAppearance(short& nAppearance)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_APPEARANCE, var);
ATLASSERT(var.vt == VT_I2 || var.vt == VT_UI2 || var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
nAppearance = var.iVal;
return hRes;
}
HRESULT GetAmbientBackColor(OLE_COLOR& BackColor)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_BACKCOLOR, var);
ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
BackColor = var.lVal;
return hRes;
}
HRESULT GetAmbientDisplayName(BSTR& bstrDisplayName)
{
CComVariant var;
if (bstrDisplayName)
{
SysFreeString(bstrDisplayName);
bstrDisplayName = NULL;
}
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYNAME, var);
if (SUCCEEDED(hRes))
{
if (var.vt != VT_BSTR)
return E_FAIL;
bstrDisplayName = var.bstrVal;
var.vt = VT_EMPTY;
var.bstrVal = NULL;
}
return hRes;
}
HRESULT GetAmbientFont(IFont** ppFont)
{
// caller MUST Release the font!
if (ppFont == NULL)
return E_POINTER;
*ppFont = NULL;
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FONT, var);
ATLASSERT((var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) || FAILED(hRes));
if (SUCCEEDED(hRes) && var.pdispVal)
{
if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
hRes = var.pdispVal->QueryInterface(IID_IFont, (void**)ppFont);
else
hRes = DISP_E_BADVARTYPE;
}
return hRes;
}
HRESULT GetAmbientFontDisp(IFontDisp** ppFont)
{
// caller MUST Release the font!
if (ppFont == NULL)
return E_POINTER;
*ppFont = NULL;
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FONT, var);
ATLASSERT((var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) || FAILED(hRes));
if (SUCCEEDED(hRes) && var.pdispVal)
{
if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
hRes = var.pdispVal->QueryInterface(IID_IFontDisp, (void**)ppFont);
else
hRes = DISP_E_BADVARTYPE;
}
return hRes;
}
HRESULT GetAmbientForeColor(OLE_COLOR& ForeColor)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FORECOLOR, var);
ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
ForeColor = var.lVal;
return hRes;
}
HRESULT GetAmbientLocaleID(LCID& lcid)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_LOCALEID, var);
ATLASSERT((var.vt == VT_UI4 || var.vt == VT_I4) || FAILED(hRes));
lcid = var.lVal;
return hRes;
}
HRESULT GetAmbientScaleUnits(BSTR& bstrScaleUnits)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SCALEUNITS, var);
ATLASSERT(var.vt == VT_BSTR || FAILED(hRes));
bstrScaleUnits = var.bstrVal;
return hRes;
}
HRESULT GetAmbientTextAlign(short& nTextAlign)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_TEXTALIGN, var);
ATLASSERT(var.vt == VT_I2 || FAILED(hRes));
nTextAlign = var.iVal;
return hRes;
}
HRESULT GetAmbientUserMode(BOOL& bUserMode)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bUserMode = var.boolVal;
return hRes;
}
HRESULT GetAmbientUIDead(BOOL& bUIDead)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_UIDEAD, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bUIDead = var.boolVal;
return hRes;
}
HRESULT GetAmbientShowGrabHandles(BOOL& bShowGrabHandles)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWGRABHANDLES, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bShowGrabHandles = var.boolVal;
return hRes;
}
HRESULT GetAmbientShowHatching(BOOL& bShowHatching)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWHATCHING, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bShowHatching = var.boolVal;
return hRes;
}
HRESULT GetAmbientMessageReflect(BOOL& bMessageReflect)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bMessageReflect = var.boolVal;
return hRes;
}
HRESULT GetAmbientAutoClip(BOOL& bAutoClip)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_AUTOCLIP, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bAutoClip = var.boolVal;
return hRes;
}
HRESULT GetAmbientDisplayAsDefault(BOOL& bDisplaysDefault)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYASDEFAULT, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bDisplaysDefault = var.boolVal;
return hRes;
}
HRESULT GetAmbientSupportsMnemonics(BOOL& bSupportMnemonics)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SUPPORTSMNEMONICS, var);
ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
bSupportMnemonics = var.boolVal;
return hRes;
}
HRESULT GetAmbientPalette(HPALETTE& hPalette)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_PALETTE, var);
#ifdef _WIN64
ATLASSERT(var.vt == VT_I8 || var.vt == VT_UI8 || FAILED(hRes));
hPalette = *(HPALETTE*)&var.dblVal;
#else
ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
hPalette = reinterpret_cast<HPALETTE>(var.lVal);
#endif
return hRes;
}
HRESULT InternalGetSite(REFIID riid, void** ppUnkSite)
{
ATLASSERT(ppUnkSite != NULL);
if (ppUnkSite == NULL)
return E_POINTER;
if (m_spClientSite == NULL)
{
*ppUnkSite = NULL;
return S_OK;
}
return m_spClientSite->QueryInterface(riid, ppUnkSite);
}
BOOL DoesVerbUIActivate(LONG iVerb)
{
BOOL b = FALSE;
switch (iVerb)
{
case OLEIVERB_UIACTIVATE:
case OLEIVERB_PRIMARY:
b = TRUE;
break;
}
// if no ambient dispatch then in old style OLE container
if (DoesVerbActivate(iVerb) && m_spAmbientDispatch.p == NULL)
b = TRUE;
return b;
}
BOOL DoesVerbActivate(LONG iVerb)
{
BOOL b = FALSE;
switch (iVerb)
{
case OLEIVERB_UIACTIVATE:
case OLEIVERB_PRIMARY:
case OLEIVERB_SHOW:
case OLEIVERB_INPLACEACTIVATE:
b = TRUE;
break;
}
return b;
}
BOOL SetControlFocus(BOOL bGrab);
HRESULT IQuickActivate_QuickActivate(QACONTAINER *pQACont,
QACONTROL *pQACtrl);
HRESULT DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent);
HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL);
HRESULT IOleObject_SetClientSite(IOleClientSite *pClientSite);
HRESULT IOleObject_GetClientSite(IOleClientSite **ppClientSite);
HRESULT IOleObject_Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection);
HRESULT IOleObject_Close(DWORD dwSaveOption);
HRESULT IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel);
HRESULT IOleInPlaceObject_InPlaceDeactivate(void);
HRESULT IOleInPlaceObject_UIDeactivate(void);
HRESULT IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip);
HRESULT IViewObject_Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
LPCRECTL prcBounds, LPCRECTL prcWBounds);
HRESULT IDataObject_GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
HRESULT FireViewChange();
LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& lResult);
virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos) = 0;
virtual HRESULT ControlQueryInterface(const IID& iid, void** ppv) = 0;
virtual HRESULT OnDrawAdvanced(ATL_DRAWINFO& di);
virtual HRESULT OnDraw(ATL_DRAWINFO& /*di*/)
{
return S_OK;
}
// Attributes
public:
CComPtr<IOleInPlaceSiteWindowless> m_spInPlaceSite;
CComPtr<IDataAdviseHolder> m_spDataAdviseHolder;
CComPtr<IOleAdviseHolder> m_spOleAdviseHolder;
CComPtr<IOleClientSite> m_spClientSite;
CComPtr<IAdviseSink> m_spAdviseSink;
CComDispatchDriver m_spAmbientDispatch;
SIZE m_sizeNatural; //unscaled size in himetric
SIZE m_sizeExtent; //current extents in himetric
RECT m_rcPos; // position in pixels
#pragma warning(disable: 4510 4610) // unnamed union
union
{
HWND& m_hWndCD;
HWND* m_phWndCD;
};
#pragma warning(default: 4510 4610)
union
{
// m_nFreezeEvents is the only one actually used
int m_nFreezeEvents; // count of freezes versus thaws
// These are here to make stock properties work
IPictureDisp* m_pMouseIcon;
IPictureDisp* m_pPicture;
IFontDisp* m_pFont;
OLE_COLOR m_clrBackColor;
OLE_COLOR m_clrBorderColor;
OLE_COLOR m_clrFillColor;
OLE_COLOR m_clrForeColor;
BSTR m_bstrText;
BSTR m_bstrCaption;
BOOL m_bValid;
BOOL m_bTabStop;
BOOL m_bBorderVisible;
BOOL m_bEnabled;
LONG m_nBackStyle;
LONG m_nBorderStyle;
LONG m_nBorderWidth;
LONG m_nDrawMode;
LONG m_nDrawStyle;
LONG m_nDrawWidth;
LONG m_nFillStyle;
SHORT m_nAppearance;
LONG m_nMousePointer;
LONG m_nReadyState;
};
unsigned m_bNegotiatedWnd:1;
unsigned m_bWndLess:1;
unsigned m_bInPlaceActive:1;
unsigned m_bUIActive:1;
unsigned m_bUsingWindowRgn:1;
unsigned m_bInPlaceSiteEx:1;
unsigned m_bWindowOnly:1;
unsigned m_bRequiresSave:1;
unsigned m_bWasOnceWindowless:1;
unsigned m_bAutoSize:1; //SetExtent fails if size doesn't match existing
unsigned m_bRecomposeOnResize:1; //implies OLEMISC_RECOMPOSEONRESIZE
unsigned m_bResizeNatural:1; //resize natural extent on SetExtent
unsigned m_bDrawFromNatural:1; //instead of m_sizeExtent
unsigned m_bDrawGetDataInHimetric:1; //instead of pixels
DECLARE_VIEW_STATUS(VIEWSTATUS_OPAQUE)
};
inline HRESULT CComControlBase::IQuickActivate_QuickActivate(QACONTAINER *pQACont,
QACONTROL *pQACtrl)
{
ATLASSERT(pQACont != NULL);
ATLASSERT(pQACtrl != NULL);
if (!pQACont || !pQACtrl)
return E_POINTER;
HRESULT hRes;
ULONG uCB = pQACtrl->cbSize;
memset(pQACtrl, 0, uCB);
pQACtrl->cbSize = uCB;
// get all interfaces we are going to need
CComPtr<IOleObject> pOO;
ControlQueryInterface(IID_IOleObject, (void**)&pOO);
CComPtr<IViewObjectEx> pVOEX;
ControlQueryInterface(IID_IViewObjectEx, (void**)&pVOEX);
CComPtr<IPointerInactive> pPI;
ControlQueryInterface(IID_IPointerInactive, (void**)&pPI);
CComPtr<IProvideClassInfo2> pPCI;
ControlQueryInterface(IID_IProvideClassInfo2, (void**)&pPCI);
if (pOO == NULL || pVOEX == NULL)
return E_FAIL;
hRes = pOO->SetClientSite(pQACont->pClientSite);
if (FAILED(hRes)) {
return hRes;
}
if (pQACont->pAdviseSink != NULL)
{
ATLTRACE2(atlTraceControls,2,_T("Setting up IOleObject Advise\n"));
pVOEX->SetAdvise(DVASPECT_CONTENT, 0, pQACont->pAdviseSink);
}
CComPtr<IConnectionPointContainer> pCPC;
ControlQueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
if (pQACont->pPropertyNotifySink)
{
ATLTRACE2(atlTraceControls,2,_T("Setting up PropNotify CP\n"));
CComPtr<IConnectionPoint> pCP;
if (pCPC != NULL)
{
hRes = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
if (SUCCEEDED(hRes))
pCP->Advise(pQACont->pPropertyNotifySink, &pQACtrl->dwPropNotifyCookie);
}
}
if (pPCI)
{
GUID iidDefaultSrc;
if (SUCCEEDED(pPCI->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID,
&iidDefaultSrc)))
{
if (pQACont->pUnkEventSink)
{
ATLTRACE2(atlTraceControls,2,_T("Setting up Default Out Going Interface\n"));
CComPtr<IConnectionPoint> pCP;
if (pCPC != NULL)
{
hRes = pCPC->FindConnectionPoint(iidDefaultSrc, &pCP);
if (SUCCEEDED(hRes))
pCP->Advise(pQACont->pUnkEventSink, &pQACtrl->dwEventCookie);
}
}
}
}
// give information to container
if (pOO != NULL)
pOO->GetMiscStatus(DVASPECT_CONTENT, &pQACtrl->dwMiscStatus);
if (pVOEX != NULL)
pVOEX->GetViewStatus(&pQACtrl->dwViewStatus);
if (pPI != NULL)
pPI->GetActivationPolicy(&pQACtrl->dwPointerActivationPolicy);
return S_OK;
}
inline BOOL CComControlBase::SetControlFocus(BOOL bGrab)
{
if (m_bWndLess)
{
if (!m_bUIActive && bGrab)
if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE)))
return FALSE;
return (m_spInPlaceSite->SetFocus(bGrab) == S_OK);
}
else
{
// we've got a window.
//
if (m_bInPlaceActive)
{
HWND hwnd = (bGrab) ? m_hWndCD : ::GetParent(m_hWndCD);
if (!m_bUIActive && bGrab)
return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
else
{
if (!::IsChild(hwnd, ::GetFocus()))
::SetFocus(hwnd);
return TRUE;
}
}
}
return FALSE;
}
inline HRESULT CComControlBase::DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent)
{
HRESULT hr = S_OK;
CComQIPtr <ISpecifyPropertyPages, &IID_ISpecifyPropertyPages> spPages;
CComQIPtr <IOleObject, &IID_IOleObject> spObj;
CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
if (spSite)
{
hr = spSite->ShowPropertyFrame();
if (SUCCEEDED(hr))
return hr;
}
CComPtr<IUnknown> pUnk;
ControlQueryInterface(IID_IUnknown, (void**)&pUnk);
ATLASSERT(pUnk != NULL);
CAUUID pages;
spPages = pUnk;
if (spPages)
{
hr = spPages->GetPages(&pages);
if (SUCCEEDED(hr))
{
spObj = pUnk;
if (spObj)
{
LPOLESTR szTitle = NULL;
spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
LCID lcid;
if (FAILED(GetAmbientLocaleID(lcid)))
lcid = LOCALE_USER_DEFAULT;
hr = OleCreatePropertyFrame(hwndParent, m_rcPos.top, m_rcPos.left, szTitle,
1, &pUnk.p, pages.cElems, pages.pElems, lcid, 0, 0);
CoTaskMemFree(szTitle);
}
else
{
hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
}
CoTaskMemFree(pages.pElems);
}
}
else
{
hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
}
return hr;
}
inline HRESULT CComControlBase::InPlaceActivate(LONG iVerb, const RECT* /*prcPosRect*/)
{
HRESULT hr;
if (m_spClientSite == NULL)
return S_OK;
CComPtr<IOleInPlaceObject> pIPO;
ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
ATLASSERT(pIPO != NULL);
if (!m_bNegotiatedWnd)
{
if (!m_bWindowOnly)
// Try for windowless site
hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
if (m_spInPlaceSite)
{
m_bInPlaceSiteEx = TRUE;
// CanWindowlessActivate returns S_OK or S_FALSE
if ( m_spInPlaceSite->CanWindowlessActivate() == S_OK )
{
m_bWndLess = TRUE;
m_bWasOnceWindowless = TRUE;
}
else
{
m_bWndLess = FALSE;
}
}
else
{
m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
if (m_spInPlaceSite)
m_bInPlaceSiteEx = TRUE;
else
hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
}
}
ATLASSERT(m_spInPlaceSite);
if (!m_spInPlaceSite)
return E_FAIL;
m_bNegotiatedWnd = TRUE;
if (!m_bInPlaceActive)
{
BOOL bNoRedraw = FALSE;
if (m_bWndLess)
m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
else
{
if (m_bInPlaceSiteEx)
m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
else
{
hr = m_spInPlaceSite->CanInPlaceActivate();
// CanInPlaceActivate returns S_FALSE or S_OK
if (FAILED(hr))
return hr;
if ( hr != S_OK )
{
// CanInPlaceActivate returned S_FALSE.
return( E_FAIL );
}
m_spInPlaceSite->OnInPlaceActivate();
}
}
}
m_bInPlaceActive = TRUE;
// get location in the parent window,
// as well as some information about the parent
//
OLEINPLACEFRAMEINFO frameInfo;
RECT rcPos, rcClip;
CComPtr<IOleInPlaceFrame> spInPlaceFrame;
CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
HWND hwndParent;
if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
{
m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
&spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
if (!m_bWndLess)
{
if (m_hWndCD)
{
ShowWindow(m_hWndCD, SW_SHOW);
if (!::IsChild(m_hWndCD, ::GetFocus()))
::SetFocus(m_hWndCD);
}
else
{
HWND h = CreateControlWindow(hwndParent, rcPos);
ATLASSERT(h != NULL); // will assert if creation failed
ATLASSERT(h == m_hWndCD);
h; // avoid unused warning
}
}
pIPO->SetObjectRects(&rcPos, &rcClip);
}
CComPtr<IOleInPlaceActiveObject> spActiveObject;
ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
// Gone active by now, take care of UIACTIVATE
if (DoesVerbUIActivate(iVerb))
{
if (!m_bUIActive)
{
m_bUIActive = TRUE;
hr = m_spInPlaceSite->OnUIActivate();
if (FAILED(hr))
return hr;
SetControlFocus(TRUE);
// set ourselves up in the host.
//
if (spActiveObject)
{
if (spInPlaceFrame)
spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
if (spInPlaceUIWindow)
spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
}
if (spInPlaceFrame)
spInPlaceFrame->SetBorderSpace(NULL);
if (spInPlaceUIWindow)
spInPlaceUIWindow->SetBorderSpace(NULL);
}
}
m_spClientSite->ShowObject();
return S_OK;
}
inline HRESULT CComControlBase::SendOnDataChange(DWORD advf)
{
HRESULT hRes = S_OK;
if (m_spDataAdviseHolder)
{
CComPtr<IDataObject> pdo;
if (SUCCEEDED(ControlQueryInterface(IID_IDataObject, (void**)&pdo)))
hRes = m_spDataAdviseHolder->SendOnDataChange(pdo, 0, advf);
}
return hRes;
}
inline HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
{
ATLASSERT(pClientSite == NULL || m_spClientSite == NULL);
m_spClientSite = pClientSite;
m_spAmbientDispatch.Release();
if (m_spClientSite != NULL)
{
m_spClientSite->QueryInterface(IID_IDispatch,
(void**) &m_spAmbientDispatch.p);
}
return S_OK;
}
inline HRESULT CComControlBase::IOleObject_GetClientSite(IOleClientSite **ppClientSite)
{
ATLASSERT(ppClientSite);
if (ppClientSite == NULL)
return E_POINTER;
*ppClientSite = m_spClientSite;
if (m_spClientSite != NULL)
m_spClientSite.p->AddRef();
return S_OK;
}
inline HRESULT CComControlBase::IOleObject_Advise(IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
HRESULT hr = S_OK;
if (m_spOleAdviseHolder == NULL)
hr = CreateOleAdviseHolder(&m_spOleAdviseHolder);
if (SUCCEEDED(hr))
hr = m_spOleAdviseHolder->Advise(pAdvSink, pdwConnection);
return hr;
}
inline HRESULT CComControlBase::IOleObject_Close(DWORD dwSaveOption)
{
CComPtr<IOleInPlaceObject> pIPO;
ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
ATLASSERT(pIPO != NULL);
if (m_hWndCD)
{
if (m_spClientSite)
m_spClientSite->OnShowWindow(FALSE);
}
if (m_bInPlaceActive)
{
HRESULT hr = pIPO->InPlaceDeactivate();
if (FAILED(hr))
return hr;
ATLASSERT(!m_bInPlaceActive);
}
if (m_hWndCD)
{
ATLTRACE2(atlTraceControls,2,_T("Destroying Window\n"));
if (::IsWindow(m_hWndCD))
DestroyWindow(m_hWndCD);
m_hWndCD = NULL;
}
// handle the save flag.
//
if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
dwSaveOption == OLECLOSE_PROMPTSAVE) && m_bRequiresSave)
{
if (m_spClientSite)
m_spClientSite->SaveObject();
SendOnSave();
}
m_spInPlaceSite.Release();
m_bNegotiatedWnd = FALSE;
m_bWndLess = FALSE;
m_bInPlaceSiteEx = FALSE;
m_spAdviseSink.Release();
return S_OK;
}
inline HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
{
CComPtr<IOleInPlaceObject> pIPO;
ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
ATLASSERT(pIPO != NULL);
if (!m_bInPlaceActive)
return S_OK;
pIPO->UIDeactivate();
m_bInPlaceActive = FALSE;
// if we have a window, tell it to go away.
//
if (m_hWndCD)
{
ATLTRACE2(atlTraceControls,2,_T("Destroying Window\n"));
if (::IsWindow(m_hWndCD))
DestroyWindow(m_hWndCD);
m_hWndCD = NULL;
}
if (m_spInPlaceSite)
m_spInPlaceSite->OnInPlaceDeactivate();
return S_OK;
}
inline HRESULT CComControlBase::IOleInPlaceObject_UIDeactivate(void)
{
// if we're not UIActive, not much to do.
//
if (!m_bUIActive)
return S_OK;
m_bUIActive = FALSE;
// notify frame windows, if appropriate, that we're no longer ui-active.
//
CComPtr<IOleInPlaceFrame> spInPlaceFrame;
CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
OLEINPLACEFRAMEINFO frameInfo;
frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
RECT rcPos, rcClip;
HWND hwndParent;
// This call to GetWindow is a fix for Delphi
if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
{
m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
&spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
if (spInPlaceUIWindow)
spInPlaceUIWindow->SetActiveObject(NULL, NULL);
if (spInPlaceFrame)
spInPlaceFrame->SetActiveObject(NULL, NULL);
}
// we don't need to explicitly release the focus here since somebody
// else grabbing the focus is what is likely to cause us to get lose it
//
m_spInPlaceSite->OnUIDeactivate(FALSE);
return S_OK;
}
inline HRESULT CComControlBase::IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
{
if (prcPos == NULL || prcClip == NULL)
return E_POINTER;
m_rcPos = *prcPos;
if (m_hWndCD)
{
// the container wants us to clip, so figure out if we really
// need to
//
RECT rcIXect;
BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
HRGN tempRgn = NULL;
if (b && !EqualRect(&rcIXect, prcPos))
{
OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
tempRgn = CreateRectRgnIndirect(&rcIXect);
}
SetWindowRgn(m_hWndCD, tempRgn, TRUE);
// set our control's location, but don't change it's size at all
// [people for whom zooming is important should set that up here]
//
SIZEL size = {prcPos->right - prcPos->left, prcPos->bottom - prcPos->top};
SetWindowPos(m_hWndCD, NULL, prcPos->left,
prcPos->top, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE);
}
return S_OK;
}
inline HRESULT CComControlBase::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
{
if (dwDrawAspect != DVASPECT_CONTENT)
return DV_E_DVASPECT;
if (psizel == NULL)
return E_POINTER;
BOOL bSizeMatchesNatural =
memcmp(psizel, &m_sizeNatural, sizeof(SIZE)) == 0;
if (m_bAutoSize) //object can't do any other size
return (bSizeMatchesNatural) ? S_OK : E_FAIL;
BOOL bResized = FALSE;
if (memcmp(psizel, &m_sizeExtent, sizeof(SIZE)) != 0)
{
m_sizeExtent = *psizel;
bResized = TRUE;
}
if (m_bResizeNatural && !bSizeMatchesNatural)
{
m_sizeNatural = *psizel;
bResized = TRUE;
}
if (m_bRecomposeOnResize && bResized)
{
SendOnDataChange();
FireViewChange();
}
return S_OK;
}
inline HRESULT CComControlBase::IViewObject_Draw(DWORD dwDrawAspect, LONG lindex,
void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
LPCRECTL prcBounds, LPCRECTL prcWBounds)
{
ATLTRACE2(atlTraceControls,2,_T("Draw dwDrawAspect=%x lindex=%d ptd=%x hic=%x hdc=%x\n"),
dwDrawAspect, lindex, ptd, hicTargetDev, hdcDraw);
#ifdef _DEBUG
if (prcBounds == NULL)
ATLTRACE2(atlTraceControls,2,_T("\tprcBounds=NULL\n"));
else
ATLTRACE2(atlTraceControls,2,_T("\tprcBounds=%d,%d,%d,%d\n"), prcBounds->left,
prcBounds->top, prcBounds->right, prcBounds->bottom);
if (prcWBounds == NULL)
ATLTRACE2(atlTraceControls,2,_T("\tprcWBounds=NULL\n"));
else
ATLTRACE2(atlTraceControls,2,_T("\tprcWBounds=%d,%d,%d,%d\n"), prcWBounds->left,
prcWBounds->top, prcWBounds->right, prcWBounds->bottom);
#endif
if (prcBounds == NULL)
{
if (!m_bWndLess)
return E_INVALIDARG;
prcBounds = (RECTL*)&m_rcPos;
}
// support the aspects required for multi-pass drawing
switch (dwDrawAspect)
{
case DVASPECT_CONTENT:
case DVASPECT_OPAQUE:
case DVASPECT_TRANSPARENT:
break;
default:
ATLASSERT(FALSE);
return DV_E_DVASPECT;
break;
}
// make sure nobody forgets to do this
if (ptd == NULL)
hicTargetDev = NULL;
BOOL bOptimize = FALSE;
if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb >= sizeof(DVASPECTINFO))
bOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE);
ATL_DRAWINFO di;
memset(&di, 0, sizeof(di));
di.cbSize = sizeof(di);
di.dwDrawAspect = dwDrawAspect;
di.lindex = lindex;
di.ptd = ptd;
di.hicTargetDev = hicTargetDev;
di.hdcDraw = hdcDraw;
di.prcBounds = prcBounds;
di.prcWBounds = prcWBounds;
di.bOptimize = bOptimize;
return OnDrawAdvanced(di);
}
inline HRESULT CComControlBase::IDataObject_GetData(FORMATETC *pformatetcIn,
STGMEDIUM *pmedium)
{
if (pmedium == NULL)
return E_POINTER;
memset(pmedium, 0, sizeof(STGMEDIUM));
ATLTRACE2(atlTraceControls,2,_T("Format = %x\n"), pformatetcIn->cfFormat);
ATLTRACE2(atlTraceControls,2,_T("TYMED = %x\n"), pformatetcIn->tymed);
if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
return DATA_E_FORMATETC;
SIZEL sizeMetric, size;
if (m_bDrawFromNatural)
sizeMetric = m_sizeNatural;
else
sizeMetric = m_sizeExtent;
if (!m_bDrawGetDataInHimetric)
AtlHiMetricToPixel(&sizeMetric, &size);
else
size = sizeMetric;
RECTL rectl = {0 ,0, size.cx, size.cy};
ATL_DRAWINFO di;
memset(&di, 0, sizeof(di));
di.cbSize = sizeof(di);
di.dwDrawAspect = DVASPECT_CONTENT;
di.lindex = -1;
di.ptd = NULL;
di.hicTargetDev = NULL;
di.prcBounds = &rectl;
di.prcWBounds = &rectl;
di.bOptimize = TRUE; //we do a SaveDC/RestoreDC
di.bRectInHimetric = m_bDrawGetDataInHimetric;
// create appropriate memory metafile DC
di.hdcDraw = CreateMetaFile(NULL);
// create attribute DC according to pformatetcIn->ptd
SaveDC(di.hdcDraw);
SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
SetWindowExtEx(di.hdcDraw, rectl.right, rectl.bottom, NULL);
OnDrawAdvanced(di);
RestoreDC(di.hdcDraw, -1);
HMETAFILE hMF = CloseMetaFile(di.hdcDraw);
if (hMF == NULL)
return E_UNEXPECTED;
HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
if (NULL==hMem)
{
DeleteMetaFile(hMF);
return ResultFromScode(STG_E_MEDIUMFULL);
}
LPMETAFILEPICT pMF=(LPMETAFILEPICT)GlobalLock(hMem);
pMF->hMF=hMF;
pMF->mm=MM_ANISOTROPIC;
pMF->xExt=sizeMetric.cx;
pMF->yExt=sizeMetric.cy;
GlobalUnlock(hMem);
pmedium->tymed = TYMED_MFPICT;
pmedium->hGlobal = hMem;
pmedium->pUnkForRelease = NULL;
return S_OK;
}
inline HRESULT CComControlBase::FireViewChange()
{
if (m_bInPlaceActive)
{
// Active
if (m_hWndCD != NULL)
::InvalidateRect(m_hWndCD, NULL, TRUE); // Window based
else if (m_spInPlaceSite != NULL)
m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
}
else // Inactive
SendOnViewChange(DVASPECT_CONTENT);
return S_OK;
}
inline void CComControlBase::GetZoomInfo(ATL_DRAWINFO& di)
{
const RECTL& rcPos = *di.prcBounds;
SIZEL sizeDen;
if (m_bDrawFromNatural)
sizeDen = m_sizeNatural;
else
sizeDen = m_sizeExtent;
if (!di.bRectInHimetric)
AtlHiMetricToPixel(&sizeDen, &sizeDen);
SIZEL sizeNum = {rcPos.right-rcPos.left, rcPos.bottom-rcPos.top};
di.ZoomNum.cx = sizeNum.cx;
di.ZoomNum.cy = sizeNum.cy;
di.ZoomDen.cx = sizeDen.cx;
di.ZoomDen.cy = sizeDen.cy;
if (sizeDen.cx == 0 || sizeDen.cy == 0 ||
sizeNum.cx == 0 || sizeNum.cy == 0)
{
di.ZoomNum.cx = di.ZoomNum.cy = di.ZoomDen.cx = di.ZoomDen.cy = 1;
di.bZoomed = FALSE;
}
else if (sizeNum.cx != sizeDen.cx || sizeNum.cy != sizeDen.cy)
di.bZoomed = TRUE;
else
di.bZoomed = FALSE;
}
inline HRESULT CComControlBase::OnDrawAdvanced(ATL_DRAWINFO& di)
{
BOOL bDeleteDC = FALSE;
if (di.hicTargetDev == NULL)
{
di.hicTargetDev = AtlCreateTargetDC(di.hdcDraw, di.ptd);
bDeleteDC = (di.hicTargetDev != di.hdcDraw);
}
RECTL rectBoundsDP = *di.prcBounds;
BOOL bMetafile = GetDeviceCaps(di.hdcDraw, TECHNOLOGY) == DT_METAFILE;
if (!bMetafile)
{
::LPtoDP(di.hicTargetDev, (LPPOINT)&rectBoundsDP, 2);
SaveDC(di.hdcDraw);
SetMapMode(di.hdcDraw, MM_TEXT);
SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
SetViewportOrgEx(di.hdcDraw, 0, 0, NULL);
di.bOptimize = TRUE; //since we save the DC we can do this
}
di.prcBounds = &rectBoundsDP;
GetZoomInfo(di);
HRESULT hRes = OnDraw(di);
if (bDeleteDC)
::DeleteDC(di.hicTargetDev);
if (!bMetafile)
RestoreDC(di.hdcDraw, -1);
return hRes;
}
inline LRESULT CComControlBase::OnPaint(UINT /* uMsg */, WPARAM wParam,
LPARAM /* lParam */, BOOL& /* lResult */)
{
RECT rc;
PAINTSTRUCT ps;
HDC hdc = (wParam != NULL) ? (HDC)wParam : ::BeginPaint(m_hWndCD, &ps);
if (hdc == NULL)
return 0;
::GetClientRect(m_hWndCD, &rc);
ATL_DRAWINFO di;
memset(&di, 0, sizeof(di));
di.cbSize = sizeof(di);
di.dwDrawAspect = DVASPECT_CONTENT;
di.lindex = -1;
di.hdcDraw = hdc;
di.prcBounds = (LPCRECTL)&rc;
OnDrawAdvanced(di);
if (wParam == NULL)
::EndPaint(m_hWndCD, &ps);
return 0;
}
template <class T, class WinBase = CWindowImpl< T > >
class ATL_NO_VTABLE CComControl : public CComControlBase, public WinBase
{
public:
CComControl() : CComControlBase(m_hWnd) {}
HRESULT FireOnRequestEdit(DISPID dispID)
{
T* pT = static_cast<T*>(this);
return T::__ATL_PROP_NOTIFY_EVENT_CLASS::FireOnRequestEdit(pT->GetUnknown(), dispID);
}
HRESULT FireOnChanged(DISPID dispID)
{
T* pT = static_cast<T*>(this);
return T::__ATL_PROP_NOTIFY_EVENT_CLASS::FireOnChanged(pT->GetUnknown(), dispID);
}
virtual HRESULT ControlQueryInterface(const IID& iid, void** ppv)
{
T* pT = static_cast<T*>(this);
return pT->_InternalQueryInterface(iid, ppv);
}
virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos)
{
T* pT = static_cast<T*>(this);
return pT->Create(hWndParent, rcPos);
}
typedef CComControl< T, WinBase > thisClass;
BEGIN_MSG_MAP(thisClass)
MESSAGE_HANDLER(WM_PAINT, CComControlBase::OnPaint)
MESSAGE_HANDLER(WM_SETFOCUS, CComControlBase::OnSetFocus)
MESSAGE_HANDLER(WM_KILLFOCUS, CComControlBase::OnKillFocus)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, CComControlBase::OnMouseActivate)
END_MSG_MAP()
};
//////////////////////////////////////////////////////////////////////////////
// CComCompositeControl
#ifndef _ATL_NO_HOSTING
template <class T>
class CComCompositeControl : public CComControl< T, CAxDialogImpl< T > >
{
public:
CComCompositeControl()
{
m_hbrBackground = NULL;
}
~CComCompositeControl()
{
DeleteObject(m_hbrBackground);
}
HRESULT AdviseSinkMap(bool bAdvise)
{
if(!bAdvise && m_hWnd == NULL)
{
// window is gone, controls are already unadvised
ATLTRACE2(atlTraceControls, 1, _T("CComCompositeControl::AdviseSinkMap called after the window was destroyed\n"));
return S_OK;
}
T* pT = static_cast<T*>(this);
return AtlAdviseSinkMap(pT, bAdvise);
}
HBRUSH m_hbrBackground;
HRESULT SetBackgroundColorFromAmbient()
{
if (m_hbrBackground != NULL)
{
DeleteObject(m_hbrBackground);
m_hbrBackground = NULL;
}
OLE_COLOR clr;
HRESULT hr = GetAmbientBackColor(clr);
if (SUCCEEDED(hr))
{
COLORREF rgb;
::OleTranslateColor(clr, NULL, &rgb);
m_hbrBackground = ::CreateSolidBrush(rgb);
EnumChildWindows(m_hWnd, (WNDENUMPROC)BackgroundColorEnumProc, (LPARAM) clr);
}
return hr;
}
static BOOL CALLBACK BackgroundColorEnumProc(HWND hwnd, LPARAM l)
{
CAxWindow wnd(hwnd);
CComPtr<IAxWinAmbientDispatch> spDispatch;
wnd.QueryHost(&spDispatch);
if (spDispatch != NULL)
spDispatch->put_BackColor((OLE_COLOR)l);
return TRUE;
}
LRESULT OnDialogColor(UINT, WPARAM w, LPARAM, BOOL&)
{
HDC dc = (HDC) w;
LOGBRUSH lb;
::GetObject(m_hbrBackground, sizeof(lb), (void*)&lb);
::SetBkColor(dc, lb.lbColor);
return (LRESULT)m_hbrBackground;
}
HWND Create(HWND hWndParent, RECT& /*rcPos*/, LPARAM dwInitParam = NULL)
{
CComControl< T, CAxDialogImpl< T > >::Create(hWndParent, dwInitParam);
SetBackgroundColorFromAmbient();
if (m_hWnd != NULL)
ShowWindow(SW_SHOWNOACTIVATE);
return m_hWnd;
}
BOOL CalcExtent(SIZE& size)
{
HINSTANCE hInstance = _Module.GetResourceInstance();
LPCTSTR lpTemplateName = MAKEINTRESOURCE(T::IDD);
HRSRC hDlgTempl = FindResource(hInstance, lpTemplateName, RT_DIALOG);
if (hDlgTempl == NULL)
return FALSE;
HGLOBAL hResource = LoadResource(hInstance, hDlgTempl);
DLGTEMPLATE* pDlgTempl = (DLGTEMPLATE*)LockResource(hResource);
if (pDlgTempl == NULL)
return FALSE;
AtlGetDialogSize(pDlgTempl, &size);
AtlPixelToHiMetric(&size, &size);
return TRUE;
}
//Implementation
BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
{
hRet = S_OK;
if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
(pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
return FALSE;
// find a direct child of the dialog from the window that has focus
HWND hWndCtl = ::GetFocus();
if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
{
do
{
hWndCtl = ::GetParent(hWndCtl);
}
while (::GetParent(hWndCtl) != m_hWnd);
}
// give controls a chance to translate this message
if (::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) == 1)
return TRUE;
// special handling for keyboard messages
DWORD_PTR dwDlgCode = ::SendMessage(pMsg->hwnd, WM_GETDLGCODE, 0, 0L);
switch(pMsg->message)
{
case WM_CHAR:
if(dwDlgCode == 0) // no dlgcode, possibly an ActiveX control
return FALSE; // let the container process this
break;
case WM_KEYDOWN:
switch(LOWORD(pMsg->wParam))
{
case VK_TAB:
// prevent tab from looping inside of our dialog
if((dwDlgCode & DLGC_WANTTAB) == 0)
{
HWND hWndFirstOrLast = ::GetWindow(m_hWnd, GW_CHILD);
if (::GetKeyState(VK_SHIFT) >= 0) // not pressed
hWndFirstOrLast = GetNextDlgTabItem(hWndFirstOrLast, TRUE);
if (hWndFirstOrLast == hWndCtl)
return FALSE;
}
break;
case VK_LEFT:
case VK_UP:
case VK_RIGHT:
case VK_DOWN:
// prevent arrows from looping inside of our dialog
if((dwDlgCode & DLGC_WANTARROWS) == 0)
{
HWND hWndFirstOrLast = ::GetWindow(m_hWnd, GW_CHILD);
if (pMsg->wParam == VK_RIGHT || pMsg->wParam == VK_DOWN) // going forward
hWndFirstOrLast = GetNextDlgTabItem(hWndFirstOrLast, TRUE);
if (hWndFirstOrLast == hWndCtl)
return FALSE;
}
break;
case VK_EXECUTE:
case VK_RETURN:
case VK_ESCAPE:
case VK_CANCEL:
// we don't want to handle these, let the container do it
return FALSE;
}
break;
}
return IsDialogMessage(pMsg);
}
HRESULT IOleInPlaceObject_InPlaceDeactivate(void)
{
AdviseSinkMap(false); //unadvise
return CComControl<T, CAxDialogImpl<T> >::IOleInPlaceObject_InPlaceDeactivate();
}
virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos)
{
T* pT = static_cast<T*>(this);
HWND h = pT->Create(hWndParent, rcPos);
if (h != NULL)
AdviseSinkMap(true);
return h;
}
virtual HRESULT OnDraw(ATL_DRAWINFO& di)
{
if(!m_bInPlaceActive)
{
HPEN hPen = (HPEN)::GetStockObject(BLACK_PEN);
HBRUSH hBrush = (HBRUSH)::GetStockObject(GRAY_BRUSH);
::SelectObject(di.hdcDraw, hPen);
::SelectObject(di.hdcDraw, hBrush);
::Rectangle(di.hdcDraw, di.prcBounds->left, di.prcBounds->top, di.prcBounds->right, di.prcBounds->bottom);
::SetTextColor(di.hdcDraw, ::GetSysColor(COLOR_WINDOWTEXT));
::SetBkMode(di.hdcDraw, TRANSPARENT);
::DrawText(di.hdcDraw, _T("ATL Composite Control"), -1, (LPRECT)di.prcBounds, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
}
return S_OK;
}
typedef CComControl< T, CAxDialogImpl< T > > baseClass;
BEGIN_MSG_MAP(CComCompositeControl< T >)
MESSAGE_HANDLER(WM_CTLCOLORDLG, OnDialogColor)
MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnDialogColor)
MESSAGE_HANDLER(WM_SETFOCUS, baseClass::OnSetFocus)
MESSAGE_HANDLER(WM_KILLFOCUS, baseClass::OnKillFocus)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, baseClass::OnMouseActivate)
END_MSG_MAP()
BEGIN_SINK_MAP(T)
END_SINK_MAP()
};
#endif //_ATL_NO_HOSTING
// Forward declarations
//
template <class T> class IPersistStorageImpl;
template <class T> class IPersistPropertyBagImpl;
template <class T> class IOleControlImpl;
template <class T> class IRunnableObjectImpl;
template <class T> class IQuickActivateImpl;
template <class T> class IOleObjectImpl;
template <class T> class IPropertyPageImpl;
template <class T> class IPropertyPage2Impl;
template <class T> class IPerPropertyBrowsingImpl;
template <class T> class IViewObjectExImpl;
template <class T> class IOleWindowImpl;
template <class T> class IPointerInactiveImpl;
template <class T, class CDV> class IPropertyNotifySinkCP;
template <class T> class IBindStatusCallbackImpl;
template <class T> class CBindStatusCallback;
//////////////////////////////////////////////////////////////////////////////
// IOleControlImpl
template <class T>
class ATL_NO_VTABLE IOleControlImpl : public IOleControl
{
public:
STDMETHOD(GetControlInfo)(LPCONTROLINFO /* pCI */)
{
ATLTRACENOTIMPL(_T("IOleControlImpl::GetControlInfo"));
}
STDMETHOD(OnMnemonic)(LPMSG /* pMsg */)
{
ATLTRACENOTIMPL(_T("IOleControlImpl::OnMnemonic"));
}
STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
{
dispid;
ATLTRACE2(atlTraceControls,2,_T("IOleControlImpl::OnAmbientPropertyChange\n"));
ATLTRACE2(atlTraceControls,2,_T(" -- DISPID = %d (%d)\n"), dispid);
return S_OK;
}
STDMETHOD(FreezeEvents)(BOOL bFreeze)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleControlImpl::FreezeEvents\n"));
if (bFreeze)
pT->m_nFreezeEvents++;
else
pT->m_nFreezeEvents--;
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// IQuickActivateImpl
template <class T>
class ATL_NO_VTABLE IQuickActivateImpl : public IQuickActivate
{
public:
STDMETHOD(QuickActivate)(QACONTAINER *pQACont, QACONTROL *pQACtrl)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::QuickActivate\n"));
return pT->IQuickActivate_QuickActivate(pQACont, pQACtrl);
}
STDMETHOD(SetContentExtent)(LPSIZEL pSize)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::SetContentExtent\n"));
return pT->IOleObjectImpl<T>::SetExtent(DVASPECT_CONTENT, pSize);
}
STDMETHOD(GetContentExtent)(LPSIZEL pSize)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::GetContentExtent\n"));
return pT->IOleObjectImpl<T>::GetExtent(DVASPECT_CONTENT, pSize);
}
};
//////////////////////////////////////////////////////////////////////////////
// IOleObjectImpl
template <class T>
class ATL_NO_VTABLE IOleObjectImpl : public IOleObject
{
public:
STDMETHOD(SetClientSite)(IOleClientSite *pClientSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetClientSite\n"));
return pT->IOleObject_SetClientSite(pClientSite);
}
STDMETHOD(GetClientSite)(IOleClientSite **ppClientSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetClientSite\n"));
return pT->IOleObject_GetClientSite(ppClientSite);
}
STDMETHOD(SetHostNames)(LPCOLESTR /* szContainerApp */, LPCOLESTR /* szContainerObj */)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetHostNames\n"));
return S_OK;
}
STDMETHOD(Close)(DWORD dwSaveOption)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Close\n"));
return pT->IOleObject_Close(dwSaveOption);
}
STDMETHOD(SetMoniker)(DWORD /* dwWhichMoniker */, IMoniker* /* pmk */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::SetMoniker"));
}
STDMETHOD(GetMoniker)(DWORD /* dwAssign */, DWORD /* dwWhichMoniker */, IMoniker** /* ppmk */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::GetMoniker"));
}
STDMETHOD(InitFromData)(IDataObject* /* pDataObject */, BOOL /* fCreation */, DWORD /* dwReserved */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::InitFromData"));
}
STDMETHOD(GetClipboardData)(DWORD /* dwReserved */, IDataObject** /* ppDataObject */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::GetClipboardData"));
}
// Helpers for DoVerb - Over-rideable in user class
HRESULT DoVerbPrimary(LPCRECT prcPosRect, HWND hwndParent)
{
T* pT = static_cast<T*>(this);
BOOL bDesignMode = FALSE;
CComVariant var;
// if container doesn't support this property
// don't allow design mode
HRESULT hRes = pT->GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
if (SUCCEEDED(hRes) && var.vt == VT_BOOL && !var.boolVal)
bDesignMode = TRUE;
if (bDesignMode)
return pT->DoVerbProperties(prcPosRect, hwndParent);
else
return pT->DoVerbInPlaceActivate(prcPosRect, hwndParent);
}
HRESULT DoVerbShow(LPCRECT prcPosRect, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr;
hr = pT->OnPreVerbShow();
if (SUCCEEDED(hr))
{
hr = pT->InPlaceActivate(OLEIVERB_SHOW, prcPosRect);
if (SUCCEEDED(hr))
hr = pT->OnPostVerbShow();
}
return hr;
}
HRESULT DoVerbInPlaceActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr;
hr = pT->OnPreVerbInPlaceActivate();
if (SUCCEEDED(hr))
{
hr = pT->InPlaceActivate(OLEIVERB_INPLACEACTIVATE, prcPosRect);
if (SUCCEEDED(hr))
hr = pT->OnPostVerbInPlaceActivate();
if (SUCCEEDED(hr))
pT->FireViewChange();
}
return hr;
}
HRESULT DoVerbUIActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr = S_OK;
if (!pT->m_bUIActive)
{
hr = pT->OnPreVerbUIActivate();
if (SUCCEEDED(hr))
{
hr = pT->InPlaceActivate(OLEIVERB_UIACTIVATE, prcPosRect);
if (SUCCEEDED(hr))
hr = pT->OnPostVerbUIActivate();
}
}
return hr;
}
HRESULT DoVerbHide(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr;
hr = pT->OnPreVerbHide();
if (SUCCEEDED(hr))
{
pT->UIDeactivate();
if (pT->m_hWnd)
pT->ShowWindow(SW_HIDE);
hr = pT->OnPostVerbHide();
}
return hr;
}
HRESULT DoVerbOpen(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr;
hr = pT->OnPreVerbOpen();
if (SUCCEEDED(hr))
hr = pT->OnPostVerbOpen();
return hr;
}
HRESULT DoVerbDiscardUndo(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
HRESULT hr;
hr = pT->OnPreVerbDiscardUndo();
if (SUCCEEDED(hr))
hr = pT->OnPostVerbDiscardUndo();
return hr;
}
STDMETHOD(DoVerb)(LONG iVerb, LPMSG /* pMsg */, IOleClientSite* /* pActiveSite */, LONG /* lindex */,
HWND hwndParent, LPCRECT lprcPosRect)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::DoVerb(%d)\n"), iVerb);
ATLASSERT(pT->m_spClientSite);
HRESULT hr = E_NOTIMPL;
switch (iVerb)
{
case OLEIVERB_PRIMARY:
hr = pT->DoVerbPrimary(lprcPosRect, hwndParent);
break;
case OLEIVERB_SHOW:
hr = pT->DoVerbShow(lprcPosRect, hwndParent);
break;
case OLEIVERB_INPLACEACTIVATE:
hr = pT->DoVerbInPlaceActivate(lprcPosRect, hwndParent);
break;
case OLEIVERB_UIACTIVATE:
hr = pT->DoVerbUIActivate(lprcPosRect, hwndParent);
break;
case OLEIVERB_HIDE:
hr = pT->DoVerbHide(lprcPosRect, hwndParent);
break;
case OLEIVERB_OPEN:
hr = pT->DoVerbOpen(lprcPosRect, hwndParent);
break;
case OLEIVERB_DISCARDUNDOSTATE:
hr = pT->DoVerbDiscardUndo(lprcPosRect, hwndParent);
break;
case OLEIVERB_PROPERTIES:
hr = pT->DoVerbProperties(lprcPosRect, hwndParent);
}
return hr;
}
STDMETHOD(EnumVerbs)(IEnumOLEVERB **ppEnumOleVerb)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::EnumVerbs\n"));
ATLASSERT(ppEnumOleVerb);
if (!ppEnumOleVerb)
return E_POINTER;
return OleRegEnumVerbs(T::GetObjectCLSID(), ppEnumOleVerb);
}
STDMETHOD(Update)(void)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Update\n"));
return S_OK;
}
STDMETHOD(IsUpToDate)(void)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::IsUpToDate\n"));
return S_OK;
}
STDMETHOD(GetUserClassID)(CLSID *pClsid)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetUserClassID\n"));
ATLASSERT(pClsid);
if (!pClsid)
return E_POINTER;
*pClsid = T::GetObjectCLSID();
return S_OK;
}
STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetUserType\n"));
return OleRegGetUserType(T::GetObjectCLSID(), dwFormOfType, pszUserType);
}
STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetExtent\n"));
return pT->IOleObject_SetExtent(dwDrawAspect, psizel);
}
STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetExtent\n"));
if (dwDrawAspect != DVASPECT_CONTENT)
return E_FAIL;
if (psizel == NULL)
return E_POINTER;
*psizel = pT->m_sizeExtent;
return S_OK;
}
STDMETHOD(Advise)(IAdviseSink *pAdvSink, DWORD *pdwConnection)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Advise\n"));
return pT->IOleObject_Advise(pAdvSink, pdwConnection);
}
STDMETHOD(Unadvise)(DWORD dwConnection)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Unadvise\n"));
HRESULT hRes = E_FAIL;
if (pT->m_spOleAdviseHolder != NULL)
hRes = pT->m_spOleAdviseHolder->Unadvise(dwConnection);
return hRes;
}
STDMETHOD(EnumAdvise)(IEnumSTATDATA **ppenumAdvise)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::EnumAdvise\n"));
HRESULT hRes = E_FAIL;
if (pT->m_spOleAdviseHolder != NULL)
hRes = pT->m_spOleAdviseHolder->EnumAdvise(ppenumAdvise);
return hRes;
}
STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus)
{
ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetMiscStatus\n"));
return OleRegGetMiscStatus(T::GetObjectCLSID(), dwAspect, pdwStatus);
}
STDMETHOD(SetColorScheme)(LOGPALETTE* /* pLogpal */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::SetColorScheme"));
}
// Implementation
public:
HRESULT OnPreVerbShow() { return S_OK; }
HRESULT OnPostVerbShow() { return S_OK; }
HRESULT OnPreVerbInPlaceActivate() { return S_OK; }
HRESULT OnPostVerbInPlaceActivate() { return S_OK; }
HRESULT OnPreVerbUIActivate() { return S_OK; }
HRESULT OnPostVerbUIActivate() { return S_OK; }
HRESULT OnPreVerbHide() { return S_OK; }
HRESULT OnPostVerbHide() { return S_OK; }
HRESULT OnPreVerbOpen() { return S_OK; }
HRESULT OnPostVerbOpen() { return S_OK; }
HRESULT OnPreVerbDiscardUndo() { return S_OK; }
HRESULT OnPostVerbDiscardUndo() { return S_OK; }
};
//local struct used for implementation
#pragma pack(push, 1)
struct _ATL_DLGTEMPLATEEX
{
WORD dlgVer;
WORD signature;
DWORD helpID;
DWORD exStyle;
DWORD style;
WORD cDlgItems;
short x;
short y;
short cx;
short cy;
};
#pragma pack(pop)
//////////////////////////////////////////////////////////////////////////////
// IPropertyPageImpl
template <class T>
class ATL_NO_VTABLE IPropertyPageImpl : public IPropertyPage
{
public:
void SetDirty(BOOL bDirty)
{
T* pT = static_cast<T*>(this);
if (pT->m_bDirty != bDirty)
{
pT->m_bDirty = bDirty;
pT->m_pPageSite->OnStatusChange(bDirty ? PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE : 0);
}
}
IPropertyPageImpl()
{
T* pT = static_cast<T*>(this);
pT->m_pPageSite = NULL;
pT->m_size.cx = 0;
pT->m_size.cy = 0;
pT->m_dwTitleID = 0;
pT->m_dwHelpFileID = 0;
pT->m_dwDocStringID = 0;
pT->m_dwHelpContext = 0;
pT->m_ppUnk = NULL;
pT->m_nObjects = 0;
pT->m_bDirty = FALSE;
pT->m_hWnd = NULL;
}
~IPropertyPageImpl()
{
T* pT = static_cast<T*>(this);
if (pT->m_pPageSite != NULL)
pT->m_pPageSite->Release();
for (UINT i = 0; i < m_nObjects; i++)
pT->m_ppUnk[i]->Release();
delete[] pT->m_ppUnk;
}
// IPropertyPage
//
STDMETHOD(SetPageSite)(IPropertyPageSite *pPageSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::SetPageSite\n"));
if (!pPageSite && pT->m_pPageSite)
{
pT->m_pPageSite->Release();
pT->m_pPageSite = NULL;
return S_OK;
}
if (!pPageSite && !pT->m_pPageSite)
return S_OK;
if (pPageSite && pT->m_pPageSite)
{
ATLTRACE2(atlTraceControls,2,_T("Error : setting page site again with non NULL value\n"));
return E_UNEXPECTED;
}
pT->m_pPageSite = pPageSite;
pT->m_pPageSite->AddRef();
return S_OK;
}
STDMETHOD(Activate)(HWND hWndParent, LPCRECT pRect, BOOL /* bModal */)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Activate\n"));
if (pRect == NULL)
{
ATLTRACE2(atlTraceControls,2,_T("Error : Passed a NULL rect\n"));
return E_POINTER;
}
pT->m_hWnd = pT->Create(hWndParent);
Move(pRect);
m_size.cx = pRect->right - pRect->left;
m_size.cy = pRect->bottom - pRect->top;
return S_OK;
}
STDMETHOD(Deactivate)( void)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Deactivate\n"));
if (pT->m_hWnd)
{
ATLTRACE2(atlTraceControls,2,_T("Destroying Dialog\n"));
if (::IsWindow(pT->m_hWnd))
pT->DestroyWindow();
pT->m_hWnd = NULL;
}
return S_OK;
}
STDMETHOD(GetPageInfo)(PROPPAGEINFO *pPageInfo)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::GetPageInfo\n"));
if (pPageInfo == NULL)
{
ATLTRACE2(atlTraceControls,2,_T("Error : PROPPAGEINFO passed == NULL\n"));
return E_POINTER;
}
HRSRC hRsrc = FindResource(_Module.GetResourceInstance(),
MAKEINTRESOURCE(T::IDD), RT_DIALOG);
if (hRsrc == NULL)
{
ATLTRACE2(atlTraceControls,2,_T("Could not find resource template\n"));
return E_UNEXPECTED;
}
HGLOBAL hGlob = LoadResource(_Module.GetResourceInstance(), hRsrc);
DLGTEMPLATE* pDlgTempl = (DLGTEMPLATE*)LockResource(hGlob);
if (pDlgTempl == NULL)
{
ATLTRACE2(atlTraceControls,2,_T("Could not load resource template\n"));
return E_UNEXPECTED;
}
AtlGetDialogSize(pDlgTempl, &m_size);
pPageInfo->cb = sizeof(PROPPAGEINFO);
pPageInfo->pszTitle = LoadStringHelper(pT->m_dwTitleID);
pPageInfo->size = m_size;
pPageInfo->pszHelpFile = LoadStringHelper(pT->m_dwHelpFileID);
pPageInfo->pszDocString = LoadStringHelper(pT->m_dwDocStringID);
pPageInfo->dwHelpContext = pT->m_dwHelpContext;
return S_OK;
}
STDMETHOD(SetObjects)(ULONG nObjects, IUnknown **ppUnk)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::SetObjects\n"));
if (ppUnk == NULL)
return E_POINTER;
if (pT->m_ppUnk != NULL && pT->m_nObjects > 0)
{
for (UINT iObj = 0; iObj < pT->m_nObjects; iObj++)
pT->m_ppUnk[iObj]->Release();
delete [] pT->m_ppUnk;
}
pT->m_ppUnk = NULL;
ATLTRY(pT->m_ppUnk = new IUnknown*[nObjects]);
if (pT->m_ppUnk == NULL)
return E_OUTOFMEMORY;
for (UINT i = 0; i < nObjects; i++)
{
ppUnk[i]->AddRef();
pT->m_ppUnk[i] = ppUnk[i];
}
pT->m_nObjects = nObjects;
return S_OK;
}
STDMETHOD(Show)(UINT nCmdShow)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Show\n"));
if (pT->m_hWnd == NULL)
return E_UNEXPECTED;
ShowWindow(pT->m_hWnd, nCmdShow);
return S_OK;
}
STDMETHOD(Move)(LPCRECT pRect)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Move\n"));
if (pT->m_hWnd == NULL)
return E_UNEXPECTED;
if (pRect == NULL)
return E_POINTER;
MoveWindow(pT->m_hWnd, pRect->left, pRect->top, pRect->right - pRect->left,
pRect->bottom - pRect->top, TRUE);
return S_OK;
}
STDMETHOD(IsPageDirty)(void)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::IsPageDirty\n"));
return pT->m_bDirty ? S_OK : S_FALSE;
}
STDMETHOD(Apply)(void)
{
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Apply\n"));
return S_OK;
}
STDMETHOD(Help)(LPCOLESTR pszHelpDir)
{
T* pT = static_cast<T*>(this);
USES_CONVERSION;
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Help\n"));
CComBSTR szFullFileName(pszHelpDir);
LPOLESTR szFileName = LoadStringHelper(pT->m_dwHelpFileID);
szFullFileName.Append(OLESTR("\\"));
szFullFileName.Append(szFileName);
CoTaskMemFree(szFileName);
WinHelp(pT->m_hWnd, OLE2CT(szFullFileName), HELP_CONTEXTPOPUP, NULL);
return S_OK;
}
STDMETHOD(TranslateAccelerator)(MSG *pMsg)
{
ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::TranslateAccelerator\n"));
T* pT = static_cast<T*>(this);
if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
(pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
return S_FALSE;
return (IsDialogMessage(pT->m_hWnd, pMsg)) ? S_OK : S_FALSE;
}
IPropertyPageSite* m_pPageSite;
IUnknown** m_ppUnk;
ULONG m_nObjects;
SIZE m_size;
UINT m_dwTitleID;
UINT m_dwHelpFileID;
UINT m_dwDocStringID;
DWORD m_dwHelpContext;
BOOL m_bDirty;
//methods
public:
BEGIN_MSG_MAP(IPropertyPageImpl<T>)
MESSAGE_HANDLER(WM_STYLECHANGING, OnStyleChange)
END_MSG_MAP()
LRESULT OnStyleChange(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
{
if (wParam == GWL_EXSTYLE)
{
LPSTYLESTRUCT lpss = (LPSTYLESTRUCT) lParam;
lpss->styleNew |= WS_EX_CONTROLPARENT;
return 0;
}
return 1;
}
LPOLESTR LoadStringHelper(UINT idRes)
{
USES_CONVERSION;
TCHAR szTemp[_MAX_PATH];
LPOLESTR sz;
sz = (LPOLESTR)CoTaskMemAlloc(_MAX_PATH*sizeof(OLECHAR));
if (sz == NULL)
return NULL;
sz[0] = NULL;
if (LoadString(_Module.GetResourceInstance(), idRes, szTemp, _MAX_PATH))
ocscpy(sz, T2OLE(szTemp));
else
{
ATLTRACE2(atlTraceControls,2,_T("Error : Failed to load string from res\n"));
}
return sz;
}
};
//////////////////////////////////////////////////////////////////////////////
// IPropertyPage2Impl
template <class T>
class ATL_NO_VTABLE IPropertyPage2Impl : public IPropertyPageImpl<T>
{
public:
STDMETHOD(EditProperty)(DISPID dispID)
{
ATLTRACENOTIMPL(_T("IPropertyPage2Impl::EditProperty\n"));
}
};
//////////////////////////////////////////////////////////////////////////////
// IPerPropertyBrowsingImpl
template <class T>
class ATL_NO_VTABLE IPerPropertyBrowsingImpl : public IPerPropertyBrowsing
{
public:
STDMETHOD(GetDisplayString)(DISPID dispID,BSTR *pBstr)
{
ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::GetDisplayString\n"));
T* pT = static_cast<T*>(this);
*pBstr = NULL;
CComVariant var;
if (FAILED(CComDispatchDriver::GetProperty(pT, dispID, &var)))
return S_FALSE;
BSTR bstrTemp = var.bstrVal;
if (var.vt != VT_BSTR)
{
CComVariant varDest;
if (FAILED(::VariantChangeType(&varDest, &var, VARIANT_NOVALUEPROP, VT_BSTR)))
return S_FALSE;
bstrTemp = varDest.bstrVal;
}
*pBstr = SysAllocString(bstrTemp);
if (*pBstr == NULL)
return E_OUTOFMEMORY;
return S_OK;
}
STDMETHOD(MapPropertyToPage)(DISPID dispID, CLSID *pClsid)
{
ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::MapPropertyToPage\n"));
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
ATLASSERT(pMap != NULL);
for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (pMap[i].szDesc == NULL)
continue;
// reject data entry types
if (pMap[i].dwSizeData != 0)
continue;
if (pMap[i].dispid == dispID)
{
ATLASSERT(pMap[i].pclsidPropPage != NULL);
*pClsid = *(pMap[i].pclsidPropPage);
return S_OK;
}
}
*pClsid = CLSID_NULL;
return E_INVALIDARG;
}
STDMETHOD(GetPredefinedStrings)(DISPID dispID, CALPOLESTR *pCaStringsOut,CADWORD *pCaCookiesOut)
{
dispID;
ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::GetPredefinedStrings\n"));
if (pCaStringsOut == NULL || pCaCookiesOut == NULL)
return E_POINTER;
pCaStringsOut->cElems = 0;
pCaStringsOut->pElems = NULL;
pCaCookiesOut->cElems = 0;
pCaCookiesOut->pElems = NULL;
return S_OK;
}
STDMETHOD(GetPredefinedValue)(DISPID /*dispID*/, DWORD /*dwCookie*/, VARIANT* /*pVarOut*/)
{
ATLTRACENOTIMPL(_T("IPerPropertyBrowsingImpl::GetPredefinedValue"));
}
};
//////////////////////////////////////////////////////////////////////////////
// IViewObjectExImpl
template <class T>
class ATL_NO_VTABLE IViewObjectExImpl : public IViewObjectEx
{
public:
STDMETHOD(Draw)(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
LPCRECTL prcBounds, LPCRECTL prcWBounds,
BOOL (__stdcall * /*pfnContinue*/)(DWORD_PTR dwContinue),
DWORD_PTR /*dwContinue*/)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::Draw\n"));
return pT->IViewObject_Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
prcBounds, prcWBounds);
}
STDMETHOD(GetColorSet)(DWORD /* dwDrawAspect */,LONG /* lindex */, void* /* pvAspect */, DVTARGETDEVICE* /* ptd */, HDC /* hicTargetDev */, LOGPALETTE** /* ppColorSet */)
{
ATLTRACENOTIMPL(_T("IViewObjectExImpl::GetColorSet"));
}
STDMETHOD(Freeze)(DWORD /* dwDrawAspect */, LONG /* lindex */, void* /* pvAspect */,DWORD* /* pdwFreeze */)
{
ATLTRACENOTIMPL(_T("IViewObjectExImpl::Freeze"));
}
STDMETHOD(Unfreeze)(DWORD /* dwFreeze */)
{
ATLTRACENOTIMPL(_T("IViewObjectExImpl::Unfreeze"));
}
STDMETHOD(SetAdvise)(DWORD /* aspects */, DWORD /* advf */, IAdviseSink* pAdvSink)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::SetAdvise\n"));
pT->m_spAdviseSink = pAdvSink;
return S_OK;
}
STDMETHOD(GetAdvise)(DWORD* /* pAspects */, DWORD* /* pAdvf */, IAdviseSink** ppAdvSink)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetAdvise\n"));
if (ppAdvSink != NULL)
{
*ppAdvSink = pT->m_spAdviseSink;
if (pT->m_spAdviseSink)
pT->m_spAdviseSink.p->AddRef();
}
return S_OK;
}
// IViewObject2
//
STDMETHOD(GetExtent)(DWORD /* dwDrawAspect */, LONG /* lindex */, DVTARGETDEVICE* /* ptd */, LPSIZEL lpsizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetExtent\n"));
*lpsizel = pT->m_sizeExtent;
return S_OK;
}
// IViewObjectEx
//
STDMETHOD(GetRect)(DWORD /* dwAspect */, LPRECTL /* pRect */)
{
ATLTRACENOTIMPL(_T("IViewObjectExImpl::GetRect"));
}
STDMETHOD(GetViewStatus)(DWORD* pdwStatus)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetViewStatus\n"));
*pdwStatus = pT->_GetViewStatus();
return S_OK;
}
STDMETHOD(QueryHitPoint)(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG /* lCloseHint */, DWORD *pHitResult)
{
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::QueryHitPoint\n"));
if (dwAspect == DVASPECT_CONTENT)
{
*pHitResult = PtInRect(pRectBounds, ptlLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
ATLTRACE2(atlTraceControls,2,_T("Wrong DVASPECT\n"));
return E_FAIL;
}
STDMETHOD(QueryHitRect)(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT prcLoc, LONG /* lCloseHint */, DWORD* pHitResult)
{
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::QueryHitRect\n"));
if (dwAspect == DVASPECT_CONTENT)
{
RECT rc;
*pHitResult = UnionRect(&rc, pRectBounds, prcLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
ATLTRACE2(atlTraceControls,2,_T("Wrong DVASPECT\n"));
return E_FAIL;
}
STDMETHOD(GetNaturalExtent)(DWORD dwAspect, LONG /* lindex */, DVTARGETDEVICE* /* ptd */, HDC /* hicTargetDev */, DVEXTENTINFO* pExtentInfo , LPSIZEL psizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetNaturalExtent\n"));
HRESULT hRes = E_FAIL;
if (pExtentInfo == NULL || psizel == NULL)
hRes = E_POINTER;
else if (dwAspect == DVASPECT_CONTENT)
{
if (pExtentInfo->dwExtentMode == DVEXTENT_CONTENT)
{
*psizel = pT->m_sizeNatural;
hRes = S_OK;
}
}
return hRes;
}
public:
};
//////////////////////////////////////////////////////////////////////////////
// IOleInPlaceObjectWindowlessImpl
//
template <class T>
class ATL_NO_VTABLE IOleInPlaceObjectWindowlessImpl : public IOleInPlaceObjectWindowless
{
public:
// IOleWindow
//
// Change IOleInPlaceActiveObject::GetWindow as well
STDMETHOD(GetWindow)(HWND* phwnd)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::GetWindow\n"));
T* pT = static_cast<T*>(this);
HRESULT hRes = E_POINTER;
if (pT->m_bWasOnceWindowless)
return E_FAIL;
if (phwnd != NULL)
{
*phwnd = pT->m_hWnd;
hRes = (*phwnd == NULL) ? E_UNEXPECTED : S_OK;
}
return hRes;
}
STDMETHOD(ContextSensitiveHelp)(BOOL /* fEnterMode */)
{
ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::ContextSensitiveHelp"));
}
// IOleInPlaceObject
//
STDMETHOD(InPlaceDeactivate)(void)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::InPlaceDeactivate\n"));
return pT->IOleInPlaceObject_InPlaceDeactivate();
}
STDMETHOD(UIDeactivate)(void)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::UIDeactivate\n"));
return pT->IOleInPlaceObject_UIDeactivate();
}
STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip)
{
T* pT = static_cast<T*>(this);
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::SetObjectRects\n"));
return pT->IOleInPlaceObject_SetObjectRects(prcPos, prcClip);
}
STDMETHOD(ReactivateAndUndo)(void)
{
ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::ReactivateAndUndo"));
}
// IOleInPlaceObjectWindowless
//
STDMETHOD(OnWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::OnWindowMessage\n"));
T* pT = static_cast<T*>(this);
BOOL b = pT->ProcessWindowMessage(pT->m_hWnd, msg, wParam, lParam, *plResult);
return b ? S_OK : S_FALSE;
}
STDMETHOD(GetDropTarget)(IDropTarget** /* ppDropTarget */)
{
ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::GetDropTarget"));
}
};
//////////////////////////////////////////////////////////////////////////////
// IOleInPlaceActiveObjectImpl
//
template <class T>
class ATL_NO_VTABLE IOleInPlaceActiveObjectImpl : public IOleInPlaceActiveObject
{
public:
// IOleWindow
//
// Change IOleInPlaceObjectWindowless::GetWindow as well
STDMETHOD(GetWindow)(HWND *phwnd)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::GetWindow\n"));
T* pT = static_cast<T*>(this);
HRESULT hRes = E_POINTER;
if (pT->m_bWasOnceWindowless)
return E_FAIL;
if (phwnd != NULL)
{
*phwnd = pT->m_hWnd;
hRes = (*phwnd == NULL) ? E_UNEXPECTED : S_OK;
}
return hRes;
}
STDMETHOD(ContextSensitiveHelp)(BOOL /* fEnterMode */)
{
ATLTRACENOTIMPL(_T("IOleInPlaceActiveObjectImpl::ContextSensitiveHelp"));
}
// IOleInPlaceActiveObject
//
STDMETHOD(TranslateAccelerator)(LPMSG pMsg)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::TranslateAccelerator\n"));
T* pT = static_cast<T*>(this);
HRESULT hRet = S_OK;
if (pT->PreTranslateAccelerator(pMsg, hRet))
return hRet;
CComPtr<IOleControlSite> spCtlSite;
hRet = pT->InternalGetSite(IID_IOleControlSite, (void**)&spCtlSite);
if (SUCCEEDED(hRet))
{
if (spCtlSite != NULL)
{
DWORD dwKeyMod = 0;
if (::GetKeyState(VK_SHIFT) < 0)
dwKeyMod += 1; // KEYMOD_SHIFT
if (::GetKeyState(VK_CONTROL) < 0)
dwKeyMod += 2; // KEYMOD_CONTROL
if (::GetKeyState(VK_MENU) < 0)
dwKeyMod += 4; // KEYMOD_ALT
hRet = spCtlSite->TranslateAccelerator(pMsg, dwKeyMod);
}
else
hRet = S_FALSE;
}
return (hRet == S_OK) ? S_OK : S_FALSE;
}
STDMETHOD(OnFrameWindowActivate)(BOOL /* fActivate */)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::OnFrameWindowActivate\n"));
return S_OK;
}
STDMETHOD(OnDocWindowActivate)(BOOL fActivate)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::OnDocWindowActivate\n"));
T* pT = static_cast<T*>(this);
if (fActivate == FALSE)
pT->IOleInPlaceObject_UIDeactivate();
return S_OK;
}
STDMETHOD(ResizeBorder)(LPCRECT /* prcBorder */, IOleInPlaceUIWindow* /* pUIWindow */, BOOL /* fFrameWindow */)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::ResizeBorder\n"));
return S_OK;
}
STDMETHOD(EnableModeless)(BOOL /* fEnable */)
{
ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::EnableModeless\n"));
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// IPointerInactiveImpl
template <class T>
class ATL_NO_VTABLE IPointerInactiveImpl : public IPointerInactive
{
public:
// IPointerInactive
//
STDMETHOD(GetActivationPolicy)(DWORD *pdwPolicy)
{
ATLTRACENOTIMPL(_T("IPointerInactiveImpl::GetActivationPolicy"));
}
STDMETHOD(OnInactiveMouseMove)(LPCRECT pRectBounds, long x, long y, DWORD dwMouseMsg)
{
ATLTRACENOTIMPL(_T("IPointerInactiveImpl::OnInactiveMouseMove"));
}
STDMETHOD(OnInactiveSetCursor)(LPCRECT pRectBounds, long x, long y, DWORD dwMouseMsg, BOOL fSetAlways)
{
ATLTRACENOTIMPL(_T("IPointerInactiveImpl::OnInactiveSetCursor"));
}
};
//////////////////////////////////////////////////////////////////////////////
// IRunnableObjectImpl
template <class T>
class ATL_NO_VTABLE IRunnableObjectImpl : public IRunnableObject
{
public:
// IRunnableObject
//
STDMETHOD(GetRunningClass)(LPCLSID lpClsid)
{
ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::GetRunningClass\n"));
*lpClsid = GUID_NULL;
return E_UNEXPECTED;
}
STDMETHOD(Run)(LPBINDCTX)
{
ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::Run\n"));
return S_OK;
}
virtual BOOL STDMETHODCALLTYPE IsRunning()
{
ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::IsRunning\n"));
return TRUE;
}
STDMETHOD(LockRunning)(BOOL /*fLock*/, BOOL /*fLastUnlockCloses*/)
{
ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::LockRunning\n"));
return S_OK;
}
STDMETHOD(SetContainedObject)(BOOL /*fContained*/)
{
ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::SetContainedObject\n"));
return S_OK;
}
};
//////////////////////////////////////////////////////////////////////////////
// IDataObjectImpl
template <class T>
class ATL_NO_VTABLE IDataObjectImpl : public IDataObject
{
public:
STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::GetData\n"));
T* pT = (T*) this;
return pT->IDataObject_GetData(pformatetcIn, pmedium);
}
STDMETHOD(GetDataHere)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */)
{
ATLTRACENOTIMPL(_T("IDataObjectImpl::GetDataHere"));
}
STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */)
{
ATLTRACENOTIMPL(_T("IDataObjectImpl::QueryGetData"));
}
STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
{
ATLTRACENOTIMPL(_T("IDataObjectImpl::GetCanonicalFormatEtc"));
}
STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
{
ATLTRACENOTIMPL(_T("IDataObjectImpl::SetData"));
}
STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
{
ATLTRACENOTIMPL(_T("IDataObjectImpl::EnumFormatEtc"));
}
STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
DWORD *pdwConnection)
{
ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::DAdvise\n"));
T* pT = static_cast<T*>(this);
HRESULT hr = S_OK;
if (pT->m_spDataAdviseHolder == NULL)
hr = CreateDataAdviseHolder(&pT->m_spDataAdviseHolder);
if (hr == S_OK)
hr = pT->m_spDataAdviseHolder->Advise((IDataObject*)this, pformatetc, advf, pAdvSink, pdwConnection);
return hr;
}
STDMETHOD(DUnadvise)(DWORD dwConnection)
{
ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::DUnadvise\n"));
T* pT = static_cast<T*>(this);
HRESULT hr = S_OK;
if (pT->m_spDataAdviseHolder == NULL)
hr = OLE_E_NOCONNECTION;
else
hr = pT->m_spDataAdviseHolder->Unadvise(dwConnection);
return hr;
}
STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
{
ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::EnumDAdvise\n"));
T* pT = static_cast<T*>(this);
HRESULT hr = E_FAIL;
if (pT->m_spDataAdviseHolder != NULL)
hr = pT->m_spDataAdviseHolder->EnumAdvise(ppenumAdvise);
return hr;
}
};
//////////////////////////////////////////////////////////////////////////////
// IPropertyNotifySinkCP
template <class T, class CDV = CComDynamicUnkArray >
class ATL_NO_VTABLE IPropertyNotifySinkCP :
public IConnectionPointImpl<T, &IID_IPropertyNotifySink, CDV>
{
public:
typedef CFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS;
};
//////////////////////////////////////////////////////////////////////////////
// IObjectSafety
//
// 2nd template parameter is the supported safety e.g.
// INTERFACESAFE_FOR_UNTRUSTED_CALLER - safe for scripting
// INTERFACESAFE_FOR_UNTRUSTED_DATA - safe for initialization from data
template <class T, DWORD dwSupportedSafety>
class ATL_NO_VTABLE IObjectSafetyImpl : public IObjectSafety
{
public:
IObjectSafetyImpl()
{
m_dwCurrentSafety = 0;
}
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
{
ATLTRACE2(atlTraceControls,2,_T("IObjectSafetyImpl2::GetInterfaceSafetyOptions\n"));
T* pT = static_cast<T*>(this);
if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
return E_POINTER;
HRESULT hr;
IUnknown* pUnk;
// Check if we support this interface
hr = pT->GetUnknown()->QueryInterface(riid, (void**)&pUnk);
if (SUCCEEDED(hr))
{
// We support this interface so set the safety options accordingly
pUnk->Release(); // Release the interface we just acquired
*pdwSupportedOptions = dwSupportedSafety;
*pdwEnabledOptions = m_dwCurrentSafety;
}
else
{
// We don't support this interface
*pdwSupportedOptions = 0;
*pdwEnabledOptions = 0;
}
return hr;
}
STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
ATLTRACE2(atlTraceControls,2,_T("IObjectSafetyImpl2::SetInterfaceSafetyOptions\n"));
T* pT = static_cast<T*>(this);
IUnknown* pUnk;
// Check if we support the interface and return E_NOINTEFACE if we don't
if (FAILED(pT->GetUnknown()->QueryInterface(riid, (void**)&pUnk)))
return E_NOINTERFACE;
pUnk->Release(); // Release the interface we just acquired
// If we are asked to set options we don't support then fail
if (dwOptionSetMask & ~dwSupportedSafety)
return E_FAIL;
// Set the safety options we have been asked to
m_dwCurrentSafety = m_dwCurrentSafety & ~dwOptionSetMask | dwEnabledOptions;
return S_OK;
}
DWORD m_dwCurrentSafety;
};
template <class T>
class ATL_NO_VTABLE IOleLinkImpl : public IOleLink
{
STDMETHOD(SetUpdateOptions)(DWORD /* dwUpdateOpt */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::SetUpdateOptions"));
}
STDMETHOD(GetUpdateOptions)(DWORD* /* pdwUpdateOpt */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::GetUpdateOptions"));
}
STDMETHOD(SetSourceMoniker)(IMoniker* /* pmk */, REFCLSID /* rclsid */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::SetSourceMoniker"));
}
STDMETHOD(GetSourceMoniker)(IMoniker** /* ppmk */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::GetSourceMoniker"));
};
STDMETHOD(SetSourceDisplayName)(LPCOLESTR /* pszStatusText */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::SetSourceDisplayName"));
}
STDMETHOD(GetSourceDisplayName)(LPOLESTR *ppszDisplayName)
{
ATLTRACE2(atlTraceControls,2,_T("IOleLink::GetSourceDisplayName\n"));
*ppszDisplayName = NULL;
return E_FAIL;
}
STDMETHOD(BindToSource)(DWORD /* bindflags */, IBindCtx* /* pbc */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::BindToSource\n"));
};
STDMETHOD(BindIfRunning)()
{
ATLTRACE2(atlTraceControls,2,_T("IOleLinkImpl::BindIfRunning\n"));
return S_OK;
};
STDMETHOD(GetBoundSource)(IUnknown** /* ppunk */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::GetBoundSource"));
};
STDMETHOD(UnbindSource)()
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::UnbindSource"));
};
STDMETHOD(Update)(IBindCtx* /* pbc */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::Update"));
};
};
template <class T>
class ATL_NO_VTABLE CBindStatusCallback :
public CComObjectRootEx<T::_ThreadModel::ThreadModelNoCS>,
public IBindStatusCallback
{
typedef void (T::*ATL_PDATAAVAILABLE)(CBindStatusCallback<T>* pbsc, BYTE* pBytes, DWORD dwSize);
public:
BEGIN_COM_MAP(CBindStatusCallback<T>)
COM_INTERFACE_ENTRY(IBindStatusCallback)
END_COM_MAP()
CBindStatusCallback()
{
m_pT = NULL;
m_pFunc = NULL;
}
~CBindStatusCallback()
{
ATLTRACE2(atlTraceControls,2,_T("~CBindStatusCallback\n"));
}
STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pBinding)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnStartBinding\n"));
m_spBinding = pBinding;
return S_OK;
}
STDMETHOD(GetPriority)(LONG *pnPriority)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::GetPriority"));
HRESULT hr = S_OK;
if (pnPriority)
*pnPriority = THREAD_PRIORITY_NORMAL;
else
hr = E_INVALIDARG;
return S_OK;
}
STDMETHOD(OnLowResource)(DWORD reserved)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnLowResource"));
return S_OK;
}
STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnProgress"));
return S_OK;
}
STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR szError)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnStopBinding\n"));
(m_pT->*m_pFunc)(this, NULL, 0);
m_spBinding.Release();
m_spBindCtx.Release();
m_spMoniker.Release();
return S_OK;
}
STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::GetBindInfo\n"));
if (pbindInfo==NULL || pbindInfo->cbSize==0 || pgrfBINDF==NULL)
return E_INVALIDARG;
*pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
ULONG cbSize = pbindInfo->cbSize; // remember incoming cbSize
memset(pbindInfo, 0, cbSize); // zero out structure
pbindInfo->cbSize = cbSize; // restore cbSize
pbindInfo->dwBindVerb = BINDVERB_GET; // set verb
return S_OK;
}
STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnDataAvailable\n"));
HRESULT hr = S_OK;
// Get the Stream passed
if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
{
if (!m_spStream && pstgmed->tymed == TYMED_ISTREAM)
m_spStream = pstgmed->pstm;
}
DWORD dwRead = dwSize - m_dwTotalRead; // Minimum amount available that hasn't been read
DWORD dwActuallyRead = 0; // Placeholder for amount read during this pull
// If there is some data to be read then go ahead and read them
if (m_spStream)
{
if (dwRead > 0)
{
BYTE* pBytes = NULL;
ATLTRY(pBytes = new BYTE[dwRead + 1]);
if (pBytes == NULL)
return E_OUTOFMEMORY;
hr = m_spStream->Read(pBytes, dwRead, &dwActuallyRead);
if (SUCCEEDED(hr))
{
pBytes[dwActuallyRead] = 0;
if (dwActuallyRead>0)
{
(m_pT->*m_pFunc)(this, pBytes, dwActuallyRead);
m_dwTotalRead += dwActuallyRead;
}
}
delete[] pBytes;
}
}
if (BSCF_LASTDATANOTIFICATION & grfBSCF)
m_spStream.Release();
return hr;
}
STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown *punk)
{
ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnObjectAvailable"));
return S_OK;
}
HRESULT _StartAsyncDownload(BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative)
{
m_dwTotalRead = 0;
m_dwAvailableToRead = 0;
HRESULT hr = S_OK;
CComQIPtr<IServiceProvider, &IID_IServiceProvider> spServiceProvider(pUnkContainer);
CComPtr<IBindHost> spBindHost;
CComPtr<IStream> spStream;
if (spServiceProvider)
spServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&spBindHost);
if (spBindHost == NULL)
{
if (bRelative)
return E_NOINTERFACE; // relative asked for, but no IBindHost
hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
if (SUCCEEDED(hr))
hr = CreateBindCtx(0, &m_spBindCtx);
if (SUCCEEDED(hr))
hr = RegisterBindStatusCallback(m_spBindCtx, static_cast<IBindStatusCallback*>(this), 0, 0L);
else
m_spMoniker.Release();
if (SUCCEEDED(hr))
hr = m_spMoniker->BindToStorage(m_spBindCtx, 0, IID_IStream, (void**)&spStream);
}
else
{
hr = CreateBindCtx(0, &m_spBindCtx);
if (SUCCEEDED(hr))
hr = RegisterBindStatusCallback(m_spBindCtx, static_cast<IBindStatusCallback*>(this), 0, 0L);
if (SUCCEEDED(hr))
{
if (bRelative)
hr = spBindHost->CreateMoniker(bstrURL, m_spBindCtx, &m_spMoniker, 0);
else
hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
}
if (SUCCEEDED(hr))
{
hr = spBindHost->MonikerBindToStorage(m_spMoniker, m_spBindCtx, static_cast<IBindStatusCallback*>(this), IID_IStream, (void**)&spStream);
ATLTRACE2(atlTraceControls,2,_T("Bound"));
}
}
return hr;
}
HRESULT StartAsyncDownload(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE)
{
m_pT = pT;
m_pFunc = pFunc;
return _StartAsyncDownload(bstrURL, pUnkContainer, bRelative);
}
static HRESULT Download(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE)
{
CComObject<CBindStatusCallback<T> > *pbsc;
HRESULT hRes = CComObject<CBindStatusCallback<T> >::CreateInstance(&pbsc);
if (FAILED(hRes))
return hRes;
return pbsc->StartAsyncDownload(pT, pFunc, bstrURL, pUnkContainer, bRelative);
}
CComPtr<IMoniker> m_spMoniker;
CComPtr<IBindCtx> m_spBindCtx;
CComPtr<IBinding> m_spBinding;
CComPtr<IStream> m_spStream;
T* m_pT;
ATL_PDATAAVAILABLE m_pFunc;
DWORD m_dwTotalRead;
DWORD m_dwAvailableToRead;
};
#define IMPLEMENT_STOCKPROP(type, fname, pname, dispid) \
HRESULT STDMETHODCALLTYPE put_##fname(type pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
T* pT = (T*) this; \
if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
return S_FALSE; \
pT->m_##pname = pname; \
pT->m_bRequiresSave = TRUE; \
pT->FireOnChanged(dispid); \
pT->FireViewChange(); \
pT->SendOnDataChange(NULL); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(type* p##pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
if (!p##pname) return E_POINTER; \
T* pT = (T*) this; \
*p##pname = pT->m_##pname; \
return S_OK; \
}
#define IMPLEMENT_BOOL_STOCKPROP(fname, pname, dispid) \
HRESULT STDMETHODCALLTYPE put_##fname(VARIANT_BOOL pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
T* pT = (T*) this; \
if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
return S_FALSE; \
pT->m_##pname = pname; \
pT->m_bRequiresSave = TRUE; \
pT->FireOnChanged(dispid); \
pT->FireViewChange(); \
pT->SendOnDataChange(NULL); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(VARIANT_BOOL* p##pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
if (!p##pname) return E_POINTER; \
T* pT = (T*) this; \
*p##pname = pT->m_##pname ? VARIANT_TRUE : VARIANT_FALSE; \
return S_OK; \
}
#define IMPLEMENT_BSTR_STOCKPROP(fname, pname, dispid) \
HRESULT STDMETHODCALLTYPE put_##fname(BSTR pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
T* pT = (T*) this; \
if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
return S_FALSE; \
if (*(&(pT->m_##pname)) != NULL) \
SysFreeString(*(&(pT->m_##pname))); \
*(&(pT->m_##pname)) = SysAllocString(pname); \
pT->m_bRequiresSave = TRUE; \
pT->FireOnChanged(dispid); \
pT->FireViewChange(); \
pT->SendOnDataChange(NULL); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(BSTR* p##pname) \
{ \
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
if (!p##pname) return E_POINTER; \
T* pT = (T*) this; \
*p##pname = SysAllocString(pT->m_##pname); \
return S_OK; \
}
template < class T, class InterfaceName, const IID* piid, const GUID* plibid>
class ATL_NO_VTABLE CStockPropImpl : public IDispatchImpl< InterfaceName, piid, plibid >
{
public:
// Font
HRESULT STDMETHODCALLTYPE put_Font(IFontDisp* pFont)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Font\n"));
if (!ppFont) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_FONT) == S_FALSE)
return S_FALSE;
pT->m_pFont = 0;
if (pFont)
{
CComQIPtr<IFont, &IID_IFont> p(pFont);
if (p)
{
CComPtr<IFont> pFont;
p->Clone(&pFont);
if (pFont)
pFont->QueryInterface(IID_IFontDisp, (void**) &pT->m_pFont);
}
}
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_FONT);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_Font(IFontDisp* pFont)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_Font\n"));
if (!pFont) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_FONT) == S_FALSE)
return S_FALSE;
pT->m_pFont = pFont;
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_FONT);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_Font(IFontDisp** ppFont)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Font\n"));
if (!ppFont) return E_POINTER;
T* pT = (T*) this;
*ppFont = pT->m_pFont;
if (*ppFont != NULL)
(*ppFont)->AddRef();
return S_OK;
}
// Picture
HRESULT STDMETHODCALLTYPE put_Picture(IPictureDisp* pPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Picture\n"));
if (!pPicture) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_PICTURE) == S_FALSE)
return S_FALSE;
pT->m_pPicture = 0;
if (pPicture)
{
CComQIPtr<IPersistStream, &IID_IPersistStream> p(pPicture);
if (p)
{
ULARGE_INTEGER l;
p->GetSizeMax(&l);
HGLOBAL hGlob = GlobalAlloc(GHND, l.LowPart);
if (hGlob)
{
CComPtr<IStream> spStream;
CreateStreamOnHGlobal(hGlob, TRUE, &spStream);
if (spStream)
{
if (SUCCEEDED(p->Save(spStream, FALSE)))
{
LARGE_INTEGER l;
l.QuadPart = 0;
spStream->Seek(l, STREAM_SEEK_SET, NULL);
OleLoadPicture(spStream, l.LowPart, FALSE, IID_IPictureDisp, (void**)&pT->m_pPicture);
}
spStream.Release();
}
GlobalFree(hGlob);
}
}
}
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_PICTURE);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_Picture(IPictureDisp* pPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_Picture\n"));
if (!pPicture) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_PICTURE) == S_FALSE)
return S_FALSE;
pT->m_pPicture = pPicture;
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_PICTURE);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_Picture(IPictureDisp** ppPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Picture\n"));
if (!ppPicture) return E_POINTER;
T* pT = (T*) this;
*ppPicture = pT->m_pPicture;
if (*ppPicture != NULL)
(*ppPicture)->AddRef();
return S_OK;
}
// MouseIcon
HRESULT STDMETHODCALLTYPE put_MouseIcon(IPictureDisp* pPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_MouseIcon\n"));
if (!pPicture) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_MOUSEICON) == S_FALSE)
return S_FALSE;
pT->m_pMouseIcon = 0;
if (pPicture)
{
CComQIPtr<IPersistStream, &IID_IPersistStream> p(pPicture);
if (p)
{
ULARGE_INTEGER l;
p->GetSizeMax(&l);
HGLOBAL hGlob = GlobalAlloc(GHND, l.LowPart);
if (hGlob)
{
CComPtr<IStream> spStream;
CreateStreamOnHGlobal(hGlob, TRUE, &spStream);
if (spStream)
{
if (SUCCEEDED(p->Save(spStream, FALSE)))
{
LARGE_INTEGER l;
l.QuadPart = 0;
spStream->Seek(l, STREAM_SEEK_SET, NULL);
OleLoadPicture(spStream, l.LowPart, FALSE, IID_IPictureDisp, (void**)&pT->m_pMouseIcon);
}
spStream.Release();
}
GlobalFree(hGlob);
}
}
}
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_MOUSEICON);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_MouseIcon(IPictureDisp* pPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_MouseIcon\n"));
if (!pPicture) return E_POINTER;
T* pT = (T*) this;
if (pT->FireOnRequestEdit(DISPID_MOUSEICON) == S_FALSE)
return S_FALSE;
pT->m_pMouseIcon = pPicture;
pT->m_bRequiresSave = TRUE;
pT->FireOnChanged(DISPID_MOUSEICON);
pT->FireViewChange();
pT->SendOnDataChange(NULL);
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_MouseIcon(IPictureDisp** ppPicture)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_MouseIcon\n"));
if (!ppPicture) return E_POINTER;
T* pT = (T*) this;
*ppPicture = pT->m_pMouseIcon;
if (*ppPicture != NULL)
(*ppPicture)->AddRef();
return S_OK;
}
IMPLEMENT_STOCKPROP(OLE_COLOR, BackColor, clrBackColor, DISPID_BACKCOLOR)
IMPLEMENT_STOCKPROP(OLE_COLOR, BorderColor, clrBorderColor, DISPID_BORDERCOLOR)
IMPLEMENT_STOCKPROP(OLE_COLOR, FillColor, clrFillColor, DISPID_FILLCOLOR)
IMPLEMENT_STOCKPROP(OLE_COLOR, ForeColor, clrForeColor, DISPID_FORECOLOR)
IMPLEMENT_BOOL_STOCKPROP(AutoSize, bAutoSize, DISPID_AUTOSIZE)
IMPLEMENT_BOOL_STOCKPROP(Valid, bValid, DISPID_VALID)
IMPLEMENT_BOOL_STOCKPROP(Enabled, bEnabled, DISPID_ENABLED)
IMPLEMENT_BOOL_STOCKPROP(TabStop, bTabStop, DISPID_TABSTOP)
IMPLEMENT_BOOL_STOCKPROP(BorderVisible, bBorderVisible, DISPID_BORDERVISIBLE)
IMPLEMENT_BSTR_STOCKPROP(Text, bstrText, DISPID_TEXT)
IMPLEMENT_BSTR_STOCKPROP(Caption, bstrCaption, DISPID_CAPTION)
HRESULT STDMETHODCALLTYPE put_Window(long /*hWnd*/)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Window\n"));
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE get_Window(HWND* phWnd)
{
ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Window\n"));
if (!phWnd) return E_POINTER;
T* pT = (T*) this;
*phWnd = pT->m_hWnd;
return S_OK;
}
IMPLEMENT_STOCKPROP(LONG, BackStyle, nBackStyle, DISPID_BACKSTYLE)
IMPLEMENT_STOCKPROP(LONG, BorderStyle, nBorderStyle, DISPID_BORDERSTYLE)
IMPLEMENT_STOCKPROP(LONG, BorderWidth, nBorderWidth, DISPID_BORDERWIDTH)
IMPLEMENT_STOCKPROP(LONG, DrawMode, nDrawMode, DISPID_DRAWMODE)
IMPLEMENT_STOCKPROP(LONG, DrawStyle, nDrawStyle, DISPID_DRAWSTYLE)
IMPLEMENT_STOCKPROP(LONG, DrawWidth, nDrawWidth, DISPID_DRAWWIDTH)
IMPLEMENT_STOCKPROP(LONG, FillStyle, nFillStyle, DISPID_FILLSTYLE)
IMPLEMENT_STOCKPROP(SHORT, Appearance, nAppearance, DISPID_APPEARANCE)
IMPLEMENT_STOCKPROP(LONG, MousePointer, nMousePointer, DISPID_MOUSEPOINTER)
IMPLEMENT_STOCKPROP(LONG, ReadyState, nReadyState, DISPID_READYSTATE)
};
#pragma pack(pop)
}; //namespace ATL
#ifndef _ATL_DLL_IMPL
#ifndef _ATL_DLL
#define _ATLCTL_IMPL
#endif
#endif
#endif // __ATLCTL_H__
#ifdef _ATLCTL_IMPL
#ifndef _ATL_DLL_IMPL
namespace ATL
{
#endif
//All exports go here
#ifndef _ATL_DLL_IMPL
}; //namespace ATL
#endif
//Prevent pulling in second time
#undef _ATLCTL_IMPL
#endif // _ATLCTL_IMPL