ATLCTL.H

// This is a part of the Active Template Library. 
// Copyright (C) 1996-1997 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")

ATLAPI_(void) AtlHiMetricToPixel(const SIZEL * lpSizeInHiMetric, LPSIZEL lpSizeInPix);
ATLAPI_(void) AtlPixelToHiMetric(const SIZEL * lpSizeInPix, LPSIZEL lpSizeInHiMetric);
ATLAPI_(HDC) AtlCreateTargetDC(HDC hdc, DVTARGETDEVICE* ptd);

// Include GUIDs for the new stock property dialogs contained in the dll MSStkProp.DLL
#include "msstkppg.h"
#define CLSID_MSStockFont CLSID_StockFontPage
#define CLSID_MSStockColor CLSID_StockColorPage
#define CLSID_MSStockPicture CLSID_StockPicturePage

#ifndef ATL_NO_NAMESPACE
namespace ATL
{
#endif

#pragma pack(push, _ATL_PACKING)

// Forward declarations
//
class ATL_NO_VTABLE CComControlBase;
template <class T> class CComControl;
class CComDispatchDriver;

struct ATL_PROPMAP_ENTRY
{
LPCOLESTR szDesc;
DISPID dispid;
const CLSID* pclsidPropPage;
const IID* piidDispatch;

};

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

//////////////////////////////////////////////////////////////////////////////
// CComDispatchDriver / Specialization of CComQIPtr<IDispatch, IID_IDispatch>
class CComDispatchDriver
{
public:
CComDispatchDriver()
{
p = NULL;
}
CComDispatchDriver(IDispatch* lp)
{
if ((p = lp) != NULL)
p->AddRef();
}
CComDispatchDriver(IUnknown* lp)
{
p=NULL;
if (lp != NULL)
lp->QueryInterface(IID_IDispatch, (void **)&p);
}
~CComDispatchDriver() { if (p) p->Release(); }
void Release() {if (p) p->Release(); p=NULL;}
operator IDispatch*() {return p;}
IDispatch& operator*() {_ASSERTE(p!=NULL); return *p; }
IDispatch** operator&() {_ASSERTE(p==NULL); return &p; }
IDispatch* operator->() {_ASSERTE(p!=NULL); return p; }
IDispatch* operator=(IDispatch* lp){return (IDispatch*)AtlComPtrAssign((IUnknown**)&p, lp);}
IDispatch* operator=(IUnknown* lp)
{
return (IDispatch*)AtlComQIPtrAssign((IUnknown**)&p, lp, IID_IDispatch);
}
BOOL operator!(){return (p == NULL) ? TRUE : FALSE;}

HRESULT GetProperty(DISPID dwDispID, VARIANT* pVar)
{
_ASSERTE(p);
return GetProperty(p, dwDispID, pVar);
}
HRESULT PutProperty(DISPID dwDispID, VARIANT* pVar)
{
_ASSERTE(p);
return PutProperty(p, dwDispID, pVar);
}

static HRESULT GetProperty(IDispatch* pDisp, DISPID dwDispID, VARIANT* pVar);
static HRESULT PutProperty(IDispatch* pDisp, DISPID dwDispID, VARIANT* pVar);
IDispatch* p;
};

//////////////////////////////////////////////////////////////////////////////
// CFirePropNotifyEvent
class CFirePropNotifyEvent
{
public:
static HRESULT FireOnRequestEdit(IUnknown* pUnk, DISPID dispID);
static HRESULT FireOnChanged(IUnknown* pUnk, DISPID dispID);
};


//////////////////////////////////////////////////////////////////////////////
// CFakeFirePropNotifyEvent
class CFakeFirePropNotifyEvent
{
public:
static HRESULT FireOnRequestEdit(IUnknown* /*pUnk*/, DISPID /*dispID*/)
{
return S_OK;
}
static HRESULT FireOnChanged(IUnknown* /*pUnk*/, DISPID /*dispID*/)
{
return S_OK;
}
};


typedef CFakeFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS;

//////////////////////////////////////////////////////////////////////////////
// CComControl
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);
ATLTRACE(_T("Control Destroyed\n"));
}

// methods
public:
// Control helper functions can go here
// non-virtuals only please
void SetDirty(BOOL bDirty)
{
m_bRequiresSave = bDirty;
}
BOOL GetDirty()
{
return m_bRequiresSave ? TRUE : FALSE;
}
void GetZoomInfo(ATL_DRAWINFO& di);
HRESULT SendOnRename(IMoniker *pmk)
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnRename(pmk);
return hRes;
}
HRESULT SendOnSave()
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnSave();
return hRes;
}
HRESULT SendOnClose()
{
HRESULT hRes = S_OK;
if (m_spOleAdviseHolder)
hRes = m_spOleAdviseHolder->SendOnClose();
return hRes;
}
HRESULT SendOnDataChange(DWORD advf = 0);
HRESULT SendOnViewChange(DWORD dwAspect, LONG lindex = -1)
{
if (m_spAdviseSink)
m_spAdviseSink->OnViewChange(dwAspect, lindex);
return S_OK;
}
LRESULT OnSetFocus(UINT /* nMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& /* bHandled */)
{
CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
if (m_bInPlaceActive && spSite)
spSite->OnFocus(TRUE);
return 0;
}

LRESULT OnKillFocus(UINT /* nMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& /* bHandled */)
{
CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
if (m_bInPlaceActive && spSite)
spSite->OnFocus(FALSE);
return 0;
}
LRESULT OnGetDlgCode(UINT /* nMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& /* bHandled */)
{
return 0;
}

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);
_ASSERTE(var.vt == VT_I2 || FAILED(hRes));
nAppearance = var.iVal;
return hRes;
}
HRESULT GetAmbientBackColor(OLE_COLOR& BackColor)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_BACKCOLOR, var);
_ASSERTE(var.vt == VT_I4 || FAILED(hRes));
BackColor = var.lVal;
return hRes;
}
HRESULT GetAmbientDisplayName(BSTR& bstrDiaplayName)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYNAME, var);
_ASSERTE(var.vt == VT_BSTR || FAILED(hRes));
bstrDiaplayName = var.bstrVal;
return hRes;
}
HRESULT GetAmbientFont(IFont** ppFont)
{
// caller MUST Release the font!
if (ppFont == NULL)
return E_POINTER;
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FONT, var);
_ASSERTE((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 GetAmbientForeColor(OLE_COLOR& ForeColor)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FORECOLOR, var);
_ASSERTE(var.vt == VT_I4 || FAILED(hRes));
ForeColor = var.lVal;
return hRes;
}
HRESULT GetAmbientLocaleID(LCID& lcid)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_LOCALEID, var);
_ASSERTE(var.vt == VT_I4 || FAILED(hRes));
lcid = var.lVal;
return hRes;
}
HRESULT GetAmbientScaleUnits(BSTR& bstrScaleUnits)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SCALEUNITS, var);
_ASSERTE(var.vt == VT_BSTR || FAILED(hRes));
bstrScaleUnits = var.bstrVal;
return hRes;
}
HRESULT GetAmbientTextAlign(short& nTextAlign)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_TEXTALIGN, var);
_ASSERTE(var.vt == VT_I2 || FAILED(hRes));
nTextAlign = var.iVal;
return hRes;
}
HRESULT GetAmbientUserMode(BOOL& bUserMode)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bUserMode = var.boolVal;
return hRes;
}
HRESULT GetAmbientUIDead(BOOL& bUIDead)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_UIDEAD, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bUIDead = var.boolVal;
return hRes;
}
HRESULT GetAmbientShowGrabHandles(BOOL& bShowGrabHandles)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWGRABHANDLES, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bShowGrabHandles = var.boolVal;
return hRes;
}
HRESULT GetAmbientShowHatching(BOOL& bShowHatching)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWHATCHING, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bShowHatching = var.boolVal;
return hRes;
}
HRESULT GetAmbientMessageReflect(BOOL& bMessageReflect)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bMessageReflect = var.boolVal;
return hRes;
}
HRESULT GetAmbientAutoClip(BOOL& bAutoClip)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_AUTOCLIP, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bAutoClip = var.boolVal;
return hRes;
}
HRESULT GetAmbientDisplayAsDefault(BOOL& bDisplaysDefault)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYASDEFAULT, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bDisplaysDefault = var.boolVal;
return hRes;
}
HRESULT GetAmbientSupportsMnemonics(BOOL& bSupportMnemonics)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SUPPORTSMNEMONICS, var);
_ASSERTE(var.vt == VT_BOOL || FAILED(hRes));
bSupportMnemonics = var.boolVal;
return hRes;
}
HRESULT GetAmbientPalette(HPALETTE& hPalette)
{
CComVariant var;
HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_PALETTE, var);
_ASSERTE(var.vt == VT_I4 || FAILED(hRes));
hPalette = reinterpret_cast<HPALETTE>(var.lVal);
return hRes;
}

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 IPersistPropertyBag_Load(LPPROPERTYBAG pPropBag,
LPERRORLOG pErrorLog, ATL_PROPMAP_ENTRY* pMap);
HRESULT IPersistPropertyBag_Save(LPPROPERTYBAG pPropBag,
BOOL fClearDirty, BOOL fSaveAllProperties, ATL_PROPMAP_ENTRY* pMap);
HRESULT ISpecifyPropertyPages_GetPages(CAUUID* pPages,
ATL_PROPMAP_ENTRY* pMap);
HRESULT DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent);
HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL);
HRESULT IPersistStreamInit_Load(LPSTREAM pStm, ATL_PROPMAP_ENTRY* pMap);
HRESULT IPersistStreamInit_Save(LPSTREAM pStm, BOOL /* fClearDirty */,
ATL_PROPMAP_ENTRY* pMap);

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 /* nMsg */, 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
union
{
HWND& m_hWndCD;
HWND* m_phWndCD;
};
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;
long 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
};

template <class T>
class ATL_NO_VTABLE CComControl : public CComControlBase, public CWindowImpl<T>
{
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);
}
};

// Forward declarations
//
template <class T> class IPersistImpl;
template <class T> class IPersistStreamInitImpl;
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 ISpecifyPropertyPagesImpl;
template <class T> class IPointerInactiveImpl;
template <class T, class CDV> class IPropertyNotifySinkCP;
template <class T> class IBindStatusCallbackImpl;
template <class T> class CBindStatusCallback;

//////////////////////////////////////////////////////////////////////////////
// IPersistImpl
template <class T>
class ATL_NO_VTABLE IPersistImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPersistImpl)

// IPersist
STDMETHOD(GetClassID)(CLSID *pClassID)
{
ATLTRACE(_T("IPersistImpl::GetClassID\n"));
T* pT = static_cast<T*>(this);
*pClassID = pT->GetObjectCLSID();
return S_OK;
}
};

#define BEGIN_PROPERTY_MAP(theClass) \
typedef _ATL_PROP_NOTIFY_EVENT_CLASS __ATL_PROP_NOTIFY_EVENT_CLASS; \
static ATL_PROPMAP_ENTRY* GetPropertyMap()\
{\
static ATL_PROPMAP_ENTRY pPropMap[] = \
{

#define PROP_ENTRY(szDesc, dispid, clsid) \
{OLESTR(szDesc), dispid, &clsid, &IID_IDispatch},

#define PROP_ENTRY_EX(szDesc, dispid, clsid, iidDispatch) \
{OLESTR(szDesc), dispid, &clsid, &iidDispatch},

#define PROP_PAGE(clsid) \
{NULL, NULL, &clsid, &IID_NULL},

#define END_PROPERTY_MAP() \
{NULL, 0, NULL, &IID_NULL} \
}; \
return pPropMap; \
}


//////////////////////////////////////////////////////////////////////////////
// IPersistStreamInitImpl
template <class T>
class ATL_NO_VTABLE IPersistStreamInitImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPersistStreamInitImpl)

// IPersist
STDMETHOD(GetClassID)(CLSID *pClassID)
{
ATLTRACE(_T("IPersistStreamInitImpl::GetClassID\n"));
T* pT = static_cast<T*>(this);
*pClassID = pT->GetObjectCLSID();
return S_OK;
}

// IPersistStream
STDMETHOD(IsDirty)()
{
ATLTRACE(_T("IPersistStreamInitImpl::IsDirty\n"));
T* pT = static_cast<T*>(this);
return (pT->m_bRequiresSave) ? S_OK : S_FALSE;
}
STDMETHOD(Load)(LPSTREAM pStm)
{
ATLTRACE(_T("IPersistStreamInitImpl::Load\n"));
T* pT = static_cast<T*>(this);
return pT->IPersistStreamInit_Load(pStm, T::GetPropertyMap());
}
STDMETHOD(Save)(LPSTREAM pStm, BOOL fClearDirty)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IPersistStreamInitImpl::Save\n"));
return pT->IPersistStreamInit_Save(pStm, fClearDirty, T::GetPropertyMap());
}
STDMETHOD(GetSizeMax)(ULARGE_INTEGER FAR* /* pcbSize */)
{
ATLTRACENOTIMPL(_T("IPersistStreamInitImpl::GetSizeMax"));
}

// IPersistStreamInit
STDMETHOD(InitNew)()
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IPersistStreamInitImpl::InitNew\n"));
pT->SendOnDataChange();
return S_OK;
}

};


//////////////////////////////////////////////////////////////////////////////
// IPersistStorageImpl
template <class T>
class ATL_NO_VTABLE IPersistStorageImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPersistStorageImpl)

// IPersist
STDMETHOD(GetClassID)(CLSID *pClassID)
{
ATLTRACE(_T("IPersistStorageImpl::GetClassID\n"));
T* pT = static_cast<T*>(this);
*pClassID = pT->GetObjectCLSID();
return S_OK;
}

// IPersistStorage
STDMETHOD(IsDirty)(void)
{
ATLTRACE(_T("IPersistStorageImpl::IsDirty\n"));
T* pT = static_cast<T*>(this);
CComPtr<IPersistStreamInit> p;
p.p = IPSI_GetIPersistStreamInit();
return (p != NULL) ? p->IsDirty() : E_FAIL;
}
STDMETHOD(InitNew)(IStorage*)
{
ATLTRACE(_T("IPersistStorageImpl::InitNew\n"));
T* pT = static_cast<T*>(this);
CComPtr<IPersistStreamInit> p;
p.p = IPSI_GetIPersistStreamInit();
return (p != NULL) ? p->InitNew() : E_FAIL;
}
STDMETHOD(Load)(IStorage* pStorage)
{
ATLTRACE(_T("IPersistStorageImpl::Load\n"));
T* pT = static_cast<T*>(this);
CComPtr<IPersistStreamInit> p;
p.p = IPSI_GetIPersistStreamInit();
HRESULT hr = E_FAIL;
if (p != NULL)
{
CComPtr<IStream> spStream;
hr = pStorage->OpenStream(OLESTR("Contents"), NULL,
STGM_DIRECT | STGM_SHARE_EXCLUSIVE, 0, &spStream);
if (SUCCEEDED(hr))
hr = p->Load(spStream);
}
return hr;
}
STDMETHOD(Save)(IStorage* pStorage, BOOL fSameAsLoad)
{
ATLTRACE(_T("IPersistStorageImpl::Save\n"));
T* pT = static_cast<T*>(this);
CComPtr<IPersistStreamInit> p;
p.p = IPSI_GetIPersistStreamInit();
HRESULT hr = E_FAIL;
if (p != NULL)
{
CComPtr<IStream> spStream;
static LPCOLESTR vszContents = OLESTR("Contents");
hr = pStorage->CreateStream(vszContents,
STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_CREATE,
0, 0, &spStream);
if (SUCCEEDED(hr))
hr = p->Save(spStream, fSameAsLoad);
}
return hr;
}
STDMETHOD(SaveCompleted)(IStorage* /* pStorage */)
{
ATLTRACE(_T("IPersistStorageImpl::SaveCompleted\n"));
return S_OK;
}
STDMETHOD(HandsOffStorage)(void)
{
ATLTRACE(_T("IPersistStorageImpl::HandsOffStorage\n"));
return S_OK;
}
private:
IPersistStreamInit* IPSI_GetIPersistStreamInit();
};

template <class T>
IPersistStreamInit* IPersistStorageImpl<T>::IPSI_GetIPersistStreamInit()
{
T* pT = static_cast<T*>(this);
IPersistStreamInit* p;
if (FAILED(pT->GetUnknown()->QueryInterface(IID_IPersistStreamInit, (void**)&p)))
pT->_InternalQueryInterface(IID_IPersistStreamInit, (void**)&p);
return p;
}

//////////////////////////////////////////////////////////////////////////////
// IPersistPropertyBagImpl
template <class T>
class ATL_NO_VTABLE IPersistPropertyBagImpl
{
public:

// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPersistPropertyBagImpl)

// IPersist
STDMETHOD(GetClassID)(CLSID *pClassID)
{
ATLTRACE(_T("IPersistPropertyBagImpl::GetClassID\n"));
T* pT = static_cast<T*>(this);
*pClassID = pT->GetObjectCLSID();
return S_OK;
}

// IPersistPropertyBag
//
STDMETHOD(InitNew)()
{
ATLTRACE(_T("IPersistPropertyBagImpl::InitNew\n"));
return S_OK;
}
STDMETHOD(Load)(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog)
{
ATLTRACE(_T("IPersistPropertyBagImpl::Load\n"));
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
_ASSERTE(pMap != NULL);
return pT->IPersistPropertyBag_Load(pPropBag, pErrorLog, pMap);
}
STDMETHOD(Save)(LPPROPERTYBAG pPropBag, BOOL fClearDirty, BOOL fSaveAllProperties)
{
ATLTRACE(_T("IPersistPropertyBagImpl::Save\n"));
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
_ASSERTE(pMap != NULL);
return pT->IPersistPropertyBag_Save(pPropBag, fClearDirty, fSaveAllProperties, pMap);
}
};


//////////////////////////////////////////////////////////////////////////////
// IOleControlImpl
template <class T>
class ATL_NO_VTABLE IOleControlImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleControlImpl)

// IOleControl methods
//
STDMETHOD(GetControlInfo)(LPCONTROLINFO /* pCI */)
{
ATLTRACENOTIMPL(_T("IOleControlImpl::GetControlInfo"));
}
STDMETHOD(OnMnemonic)(LPMSG /* pMsg */)
{
ATLTRACENOTIMPL(_T("IOleControlImpl::OnMnemonic"));
}
STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
{
dispid;
ATLTRACE(_T("IOleControlImpl::OnAmbientPropertyChange\n"));
ATLTRACE(_T(" -- DISPID = %d (%d)\n"), dispid);
return S_OK;
}
STDMETHOD(FreezeEvents)(BOOL bFreeze)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IQuickActivateImpl)

// IQuickActivate
//
STDMETHOD(QuickActivate)(QACONTAINER *pQACont, QACONTROL *pQACtrl)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IQuickActivateImpl::QuickActivate\n"));
return pT->IQuickActivate_QuickActivate(pQACont, pQACtrl);
}
STDMETHOD(SetContentExtent)(LPSIZEL pSize)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IQuickActivateImpl::SetContentExtent\n"));
return pT->IOleObjectImpl<T>::SetExtent(DVASPECT_CONTENT, pSize);
}
STDMETHOD(GetContentExtent)(LPSIZEL pSize)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IQuickActivateImpl::GetContentExtent\n"));
return pT->IOleObjectImpl<T>::GetExtent(DVASPECT_CONTENT, pSize);
}
};


//////////////////////////////////////////////////////////////////////////////
// IOleObjectImpl
template <class T>
class ATL_NO_VTABLE IOleObjectImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleObjectImpl)

// IOleObject
//
STDMETHOD(SetClientSite)(IOleClientSite *pClientSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IOleObjectImpl::SetClientSite\n"));
return pT->IOleObject_SetClientSite(pClientSite);
}
STDMETHOD(GetClientSite)(IOleClientSite **ppClientSite)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IOleObjectImpl::GetClientSite\n"));
return pT->IOleObject_GetClientSite(ppClientSite);
}
STDMETHOD(SetHostNames)(LPCOLESTR /* szContainerApp */, LPCOLESTR /* szContainerObj */)
{
ATLTRACE(_T("IOleObjectImpl::SetHostNames\n"));
return S_OK;
}
STDMETHOD(Close)(DWORD dwSaveOption)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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);
return pT->InPlaceActivate(OLEIVERB_SHOW, prcPosRect);
}
HRESULT DoVerbInPlaceActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
return pT->InPlaceActivate(OLEIVERB_INPLACEACTIVATE, prcPosRect);
}
HRESULT DoVerbUIActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
return pT->InPlaceActivate(OLEIVERB_UIACTIVATE, prcPosRect);
}
HRESULT DoVerbHide(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
T* pT = static_cast<T*>(this);
pT->UIDeactivate();
if (pT->m_hWnd)
pT->ShowWindow(SW_HIDE);
return S_OK;
}
HRESULT DoVerbOpen(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
return S_OK;
}
HRESULT DoVerbDiscardUndo(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
{
return S_OK;
}
STDMETHOD(DoVerb)(LONG iVerb, LPMSG /* lpmsg */, IOleClientSite* /* pActiveSite */, LONG /* lindex */,
HWND hwndParent, LPCRECT lprcPosRect)
{

T* pT = static_cast<T*>(this); 
ATLTRACE(_T("IOleObjectImpl::DoVerb\n"));
_ASSERTE(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)
{
ATLTRACE(_T("IOleObjectImpl::EnumVerbs\n"));
_ASSERTE(ppEnumOleVerb);
if (!ppEnumOleVerb)
return E_POINTER;
return OleRegEnumVerbs(T::GetObjectCLSID(), ppEnumOleVerb);
}
STDMETHOD(Update)(void)
{
ATLTRACE(_T("IOleObjectImpl::Update\n"));
return S_OK;
}
STDMETHOD(IsUpToDate)(void)
{
ATLTRACE(_T("IOleObjectImpl::IsUpToDate\n"));
return S_OK;
}
STDMETHOD(GetUserClassID)(CLSID *pClsid)
{
ATLTRACE(_T("IOleObjectImpl::GetUserClassID\n"));
_ASSERTE(pClsid);
if (!pClsid)
return E_POINTER;
*pClsid = T::GetObjectCLSID();
return S_OK;
}
STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType)
{
ATLTRACE(_T("IOleObjectImpl::GetUserType\n"));
return OleRegGetUserType(T::GetObjectCLSID(), dwFormOfType, pszUserType);
}
STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IOleObjectImpl::SetExtent\n"));
return pT->IOleObject_SetExtent(dwDrawAspect, psizel);
}
STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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);
ATLTRACE(_T("IOleObjectImpl::Advise\n"));
return pT->IOleObject_Advise(pAdvSink, pdwConnection);
}
STDMETHOD(Unadvise)(DWORD dwConnection)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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);
ATLTRACE(_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)
{
ATLTRACE(_T("IOleObjectImpl::GetMiscStatus\n"));
return OleRegGetMiscStatus(T::GetObjectCLSID(), dwAspect, pdwStatus);
}
STDMETHOD(SetColorScheme)(LOGPALETTE* /* pLogpal */)
{
ATLTRACENOTIMPL(_T("IOleObjectImpl::SetColorScheme"));
}
};

//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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleControlImpl)

void SetDirty(BOOL bDirty)
{
T* pT = static_cast<T*>(this);
if (!pT->m_bDirty && bDirty)
pT->m_pPageSite->OnStatusChange(PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE);
pT->m_bDirty = bDirty;
}

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);
ATLTRACE(_T("IPropertyPageImpl::SetPageSite\n"));

if (!pPageSite && pT->m_pPageSite)
{
pT->m_pPageSite->Release();
return S_OK;
}

if (!pPageSite && !pT->m_pPageSite)
return S_OK;

if (pPageSite && pT->m_pPageSite)
{
ATLTRACE(_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);
ATLTRACE(_T("IPropertyPageImpl::Activate\n"));

if (pRect == NULL)
{
ATLTRACE(_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);
ATLTRACE(_T("IPropertyPageImpl::Deactivate\n"));

if (pT->m_hWnd)
{
ATLTRACE(_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);
ATLTRACE(_T("IPropertyPageImpl::GetPageInfo\n"));

if (pPageInfo == NULL)
{
ATLTRACE(_T("Error : PROPPAGEINFO passed == NULL\n"));
return E_POINTER;
}

HRSRC hRsrc = FindResource(_Module.GetResourceInstance(),
MAKEINTRESOURCE(T::IDD), RT_DIALOG);
if (hRsrc == NULL)
{
ATLTRACE(_T("Could not find resource template\n"));
return E_UNEXPECTED;
}

HGLOBAL hGlob = LoadResource(_Module.GetResourceInstance(), hRsrc);
DLGTEMPLATE* pTemp = (DLGTEMPLATE*)LockResource(hGlob);
if (pTemp == NULL)
{
ATLTRACE(_T("Could not load resource template\n"));
return E_UNEXPECTED;
}
pT->GetDialogSize(pTemp, &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);
ATLTRACE(_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);
ATLTRACE(_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);
ATLTRACE(_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);
ATLTRACE(_T("IPropertyPageImpl::IsPageDirty\n"));
return pT->m_bDirty ? S_OK : S_FALSE;
}
STDMETHOD(Apply)(void)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IPropertyPageImpl::Apply\n"));
return S_OK;
}
STDMETHOD(Help)(LPCOLESTR pszHelpDir)
{
T* pT = static_cast<T*>(this);
USES_CONVERSION;

ATLTRACE(_T("IPropertyPageImpl::Help\n"));
WinHelp(pT->m_hWnd, OLE2CT(pszHelpDir), HELP_CONTEXTPOPUP, NULL);
return S_OK;
}
STDMETHOD(TranslateAccelerator)(MSG *pMsg)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IPropertyPageImpl::TranslateAccelerator\n"));
if (pMsg == NULL)
return E_POINTER;
LRESULT lRes;
return pT->ProcessWindowMessage(pT->m_hWnd, pMsg->message, pMsg->wParam, pMsg->lParam, lRes) ? 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 = (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
{
ATLTRACE(_T("Error : Failed to load string from res\n"));
}

return sz;
}

void GetDialogSize(const DLGTEMPLATE* pTemplate, SIZE* pSize)
{
// If the dialog has a font we use it otherwise we default
// to the system font.
if (HasFont(pTemplate))
{
TCHAR szFace[LF_FACESIZE];
WORD wFontSize = 0;
GetFont(pTemplate, szFace, &wFontSize);
GetSizeInDialogUnits(pTemplate, pSize);
ConvertDialogUnitsToPixels(szFace, wFontSize, pSize);
}
else
{
GetSizeInDialogUnits(pTemplate, pSize);
LONG nDlgBaseUnits = GetDialogBaseUnits();
pSize->cx = MulDiv(pSize->cx, LOWORD(nDlgBaseUnits), 4);
pSize->cy = MulDiv(pSize->cy, HIWORD(nDlgBaseUnits), 8);
}
}

static void ConvertDialogUnitsToPixels(LPCTSTR pszFontFace, WORD wFontSize, SIZE* pSizePixel)
{
// Attempt to create the font to be used in the dialog box
UINT cxSysChar, cySysChar;
LOGFONT lf;
HDC hDC = ::GetDC(NULL);
int cxDlg = pSizePixel->cx;
int cyDlg = pSizePixel->cy;

ZeroMemory(&lf, sizeof(LOGFONT));
lf.lfHeight = -MulDiv(wFontSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = DEFAULT_CHARSET;
lstrcpy(lf.lfFaceName, pszFontFace);

HFONT hNewFont = CreateFontIndirect(&lf);
if (hNewFont != NULL)
{
TEXTMETRIC tm;
SIZE size;
HFONT hFontOld = (HFONT)SelectObject(hDC, hNewFont);
GetTextMetrics(hDC, &tm);
cySysChar = tm.tmHeight + tm.tmExternalLeading;
::GetTextExtentPoint(hDC,
_T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"), 52,
&size);
cxSysChar = (size.cx + 26) / 52;
SelectObject(hDC, hFontOld);
DeleteObject(hNewFont);
}
else
{
// Could not create the font so just use the system's values
cxSysChar = LOWORD(GetDialogBaseUnits());
cySysChar = HIWORD(GetDialogBaseUnits());
}
::ReleaseDC(NULL, hDC);

// Translate dialog units to pixels
pSizePixel->cx = MulDiv(cxDlg, cxSysChar, 4);
pSizePixel->cy = MulDiv(cyDlg, cySysChar, 8);
}

static BOOL IsDialogEx(const DLGTEMPLATE* pTemplate)
{
return ((_ATL_DLGTEMPLATEEX*)pTemplate)->signature == 0xFFFF;
}

static BOOL HasFont(const DLGTEMPLATE* pTemplate)
{
return (DS_SETFONT &
(IsDialogEx(pTemplate) ?
((_ATL_DLGTEMPLATEEX*)pTemplate)->style : pTemplate->style));
}

static BYTE* GetFontSizeField(const DLGTEMPLATE* pTemplate)
{
BOOL bDialogEx = IsDialogEx(pTemplate);
WORD* pw;

if (bDialogEx)
pw = (WORD*)((_ATL_DLGTEMPLATEEX*)pTemplate + 1);
else
pw = (WORD*)(pTemplate + 1);

if (*pw == (WORD)-1) // Skip menu name string or ordinal
pw += 2; // WORDs
else
while(*pw++);

if (*pw == (WORD)-1) // Skip class name string or ordinal
pw += 2; // WORDs
else
while(*pw++);

while (*pw++); // Skip caption string

return (BYTE*)pw;
}

static BOOL GetFont(const DLGTEMPLATE* pTemplate, TCHAR* pszFace, WORD* pFontSize)
{
USES_CONVERSION;
if (!HasFont(pTemplate))
return FALSE;

BYTE* pb = GetFontSizeField(pTemplate);
*pFontSize = *(WORD*)pb;
// Skip over font attributes to get to the font name
pb += sizeof(WORD) * (IsDialogEx(pTemplate) ? 3 : 1);

_tcscpy(pszFace, W2T((WCHAR*)pb));
return TRUE;
}

static void GetSizeInDialogUnits(const DLGTEMPLATE* pTemplate, SIZE* pSize)
{
if (IsDialogEx(pTemplate))
{
pSize->cx = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cx;
pSize->cy = ((_ATL_DLGTEMPLATEEX*)pTemplate)->cy;
}
else
{
pSize->cx = pTemplate->cx;
pSize->cy = pTemplate->cy;
}
}
};


//////////////////////////////////////////////////////////////////////////////
// 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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPerPropertyBrowsingImpl)

STDMETHOD(GetDisplayString)(DISPID dispID,BSTR *pBstr)
{
ATLTRACE(_T("IPerPropertyBrowsingImpl::GetDisplayString\n"));
T* pT = static_cast<T*>(this);
CComVariant var;
if (FAILED(CComDispatchDriver::GetProperty(pT, dispID, &var)))
{
*pBstr = NULL;
return S_FALSE;
}

BSTR bstrTemp = var.bstrVal;
if (var.vt != VT_BSTR)
{
CComVariant varDest;
if (FAILED(::VariantChangeType(&varDest, &var, VARIANT_NOVALUEPROP, VT_BSTR)))
{
*pBstr = NULL;
return S_FALSE;
}
bstrTemp = varDest.bstrVal;
}
*pBstr = SysAllocString(bstrTemp);
return S_OK;
}

STDMETHOD(MapPropertyToPage)(DISPID dispID, CLSID *pClsid)
{
ATLTRACE(_T("IPerPropertyBrowsingImpl::MapPropertyToPage\n"));
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
_ASSERTE(pMap != NULL);
for(int i = 0; pMap[i].pclsidPropPage != NULL; i++)
{
if (pMap[i].szDesc == NULL)
continue;
if (pMap[i].dispid == dispID)
{
_ASSERTE(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;
ATLTRACE(_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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IViewObjectExImpl)

// IViewObject
//
STDMETHOD(Draw)(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
LPCRECTL prcBounds, LPCRECTL prcWBounds,
BOOL (__stdcall * /*pfnContinue*/)(DWORD dwContinue),
DWORD /*dwContinue*/)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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);
ATLTRACE(_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);
ATLTRACE(_T("IViewObjectExImpl::GetAdvise\n"));
if (ppAdvSink != NULL)
{
*ppAdvSink = pT->m_spAdviseSink;
if (pT->m_spAdviseSink)
pT->m_spAdviseSink->AddRef();
}
return S_OK;
}

// IViewObject2
//
STDMETHOD(GetExtent)(DWORD /* dwDrawAspect */, LONG /* lindex */, DVTARGETDEVICE* /* ptd */, LPSIZEL lpsizel)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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)
{
ATLTRACE(_T("IViewObjectExImpl::GetViewStatus\n"));
*pdwStatus =
// VIEWSTATUS_DVASPECTOPAQUE | VIEWSTATUS_DVASPECTTRANSPARENT |
// VIEWSTATUS_SOLIDBKGND |
VIEWSTATUS_OPAQUE;

return S_OK;
}
STDMETHOD(QueryHitPoint)(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG /* lCloseHint */, DWORD *pHitResult)
{
ATLTRACE(_T("IViewObjectExImpl::QueryHitPoint\n"));
if (dwAspect == DVASPECT_CONTENT)
{
*pHitResult = PtInRect(pRectBounds, ptlLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
ATLTRACE(_T("Wrong DVASPECT\n"));
return E_FAIL;
}
STDMETHOD(QueryHitRect)(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT prcLoc, LONG /* lCloseHint */, DWORD* pHitResult)
{
ATLTRACE(_T("IViewObjectExImpl::QueryHitRect\n"));
if (dwAspect == DVASPECT_CONTENT)
{
RECT rc;
*pHitResult = UnionRect(&rc, pRectBounds, prcLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
return S_OK;
}
ATLTRACE(_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);
ATLTRACE(_T("IViewObjectExImpl::GetNaturalExtent\n"));
HRESULT hRes = E_FAIL;
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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleInPlaceObjectWindowlessImpl)

// IOleWindow
//

// Change IOleInPlaceActiveObject::GetWindow as well
STDMETHOD(GetWindow)(HWND* phwnd)
{
ATLTRACE(_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);
ATLTRACE(_T("IOleInPlaceObjectWindowlessImpl::InPlaceDeactivate\n"));
return pT->IOleInPlaceObject_InPlaceDeactivate();
}
STDMETHOD(UIDeactivate)(void)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_T("IOleInPlaceObjectWindowlessImpl::UIDeactivate\n"));
return pT->IOleInPlaceObject_UIDeactivate();
}
STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip)
{
T* pT = static_cast<T*>(this);
ATLTRACE(_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)
{
ATLTRACE(_T("IOleInPlaceObjectWindowlessImpl::OnWindowMessage\n"));
T* pT = static_cast<T*>(this);
return pT->ProcessWindowMessage(pT->m_hWnd, msg, wParam, lParam, *plResult);
}

STDMETHOD(GetDropTarget)(IDropTarget** /* ppDropTarget */)
{
ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::GetDropTarget"));
}
};


//////////////////////////////////////////////////////////////////////////////
// IOleInPlaceActiveObjectImpl
//
template <class T>
class ATL_NO_VTABLE IOleInPlaceActiveObjectImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleInPlaceActiveObjectImpl)

// IOleWindow
//

// Change IOleInPlaceObjectWindowless::GetWindow as well
STDMETHOD(GetWindow)(HWND *phwnd)
{
ATLTRACE(_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 /* lpmsg */)
{
ATLTRACE(_T("IOleInPlaceActiveObjectImpl::TranslateAccelerator\n"));
return E_NOTIMPL;
}
STDMETHOD(OnFrameWindowActivate)(BOOL /* fActivate */)
{
ATLTRACE(_T("IOleInPlaceActiveObjectImpl::OnFrameWindowActivate\n"));
return S_OK;
}
STDMETHOD(OnDocWindowActivate)(BOOL /* fActivate */)
{
ATLTRACE(_T("IOleInPlaceActiveObjectImpl::OnDocWindowActivate\n"));
return S_OK;
}
STDMETHOD(ResizeBorder)(LPCRECT /* prcBorder */, IOleInPlaceUIWindow* /* pUIWindow */, BOOL /* fFrameWindow */)
{
ATLTRACE(_T("IOleInPlaceActiveObjectImpl::ResizeBorder\n"));
return S_OK;
}
STDMETHOD(EnableModeless)(BOOL /* fEnable */)
{
ATLTRACE(_T("IOleInPlaceActiveObjectImpl::EnableModeless\n"));
return S_OK;
}
};


//////////////////////////////////////////////////////////////////////////////
// ISpecifyPropertyPagesImpl
template <class T>
class ATL_NO_VTABLE ISpecifyPropertyPagesImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(ISpecifyPropertyPagesImpl)

// ISpecifyPropertyPages
//
STDMETHOD(GetPages)(CAUUID* pPages)
{
ATLTRACE(_T("ISpecifyPropertyPagesImpl::GetPages\n"));
T* pT = static_cast<T*>(this);
ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
return pT->ISpecifyPropertyPages_GetPages(pPages, pMap);
}
};

//////////////////////////////////////////////////////////////////////////////
// IPointerInactiveImpl
template <class T>
class ATL_NO_VTABLE IPointerInactiveImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IPointerInactiveImpl)

// 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:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IRunnableObjectImpl)

// IRunnableObject
//
STDMETHOD(GetRunningClass)(LPCLSID lpClsid)
{
ATLTRACE(_T("IRunnableObjectImpl::GetRunningClass\n"));
T* pT = static_cast<T*>(this);
*lpClsid = GUID_NULL;
return E_UNEXPECTED;
}
STDMETHOD(Run)(LPBINDCTX)
{
ATLTRACE(_T("IRunnableObjectImpl::Run\n"));
return S_OK;
}
virtual BOOL STDMETHODCALLTYPE IsRunning()
{
ATLTRACE(_T("IRunnableObjectImpl::IsRunning\n"));
return TRUE;
}
STDMETHOD(LockRunning)(BOOL /*fLock*/, BOOL /*fLastUnlockCloses*/)
{
ATLTRACE(_T("IRunnableObjectImpl::LockRunning\n"));
return S_OK;
}
STDMETHOD(SetContainedObject)(BOOL /*fContained*/)
{
ATLTRACE(_T("IRunnableObjectImpl::SetContainedObject\n"));
return S_OK;
}
};


//////////////////////////////////////////////////////////////////////////////
// IDataObjectImpl
template <class T>
class ATL_NO_VTABLE IDataObjectImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IDataObjectImpl)

// IDataObject
//
STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
{
ATLTRACE(_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)
{
ATLTRACE(_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)
{
ATLTRACE(_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)
{
ATLTRACE(_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
//

template <class T>
class ATL_NO_VTABLE IObjectSafetyImpl
{
public:
IObjectSafetyImpl()
{
m_dwSafety = 0;
}

// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IObjectSafetyImpl)

// IObjectSafety
//
STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
{
ATLTRACE(_T("IObjectSafetyImpl::GetInterfaceSafetyOptions\n"));
if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
return E_POINTER;
HRESULT hr = S_OK;
if (riid == IID_IDispatch)
{
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
*pdwEnabledOptions = m_dwSafety & INTERFACESAFE_FOR_UNTRUSTED_CALLER;
}
else
{
*pdwSupportedOptions = 0;
*pdwEnabledOptions = 0;
hr = E_NOINTERFACE;
}
return hr;
}
STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
ATLTRACE(_T("IObjectSafetyImpl::SetInterfaceSafetyOptions\n"));
// If we're being asked to set our safe for scripting option then oblige
if (riid == IID_IDispatch)
{
// Store our current safety level to return in GetInterfaceSafetyOptions
m_dwSafety = dwEnabledOptions & dwOptionSetMask;
return S_OK;
}
return E_NOINTERFACE;
}

DWORD m_dwSafety;
};


template <class T>
class ATL_NO_VTABLE IOleLinkImpl
{
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IOleLinkImpl)

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)
{
ATLTRACE(_T("IOleLink::GetSourceDisplayName\n"));
*ppszDisplayName = NULL;
return E_FAIL;
}

STDMETHOD(BindToSource)(DWORD /* bindflags */, IBindCtx* /* pbc */)
{
ATLTRACENOTIMPL(_T("IOleLinkImpl::BindToSource\n"));
};

STDMETHOD(BindIfRunning)()
{
ATLTRACE(_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 IBindStatusCallbackImpl
{
public:
// IUnknown
//
STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObject) = 0;
_ATL_DEBUG_ADDREF_RELEASE_IMPL(IBindStatusCallbackImpl)

// IBindStatusCallback
//
STDMETHOD(OnStartBinding)(DWORD /* dwReserved */, IBinding *pBinding)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnStartBinding\n"));
return S_OK;
}

STDMETHOD(GetPriority)(LONG* /* pnPriority */)
{
ATLTRACENOTIMPL(_T("IBindStatusCallbackImpl::GetPriority"));
}

STDMETHOD(OnLowResource)(DWORD /* reserved */)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnLowResource\n"));
return S_OK;
}

STDMETHOD(OnProgress)(ULONG /* ulProgress */, ULONG /* ulProgressMax */, ULONG /* ulStatusCode */, LPCWSTR /* szStatusText */)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnProgress\n"));
return S_OK;
}

STDMETHOD(OnStopBinding)(HRESULT /* hresult */, LPCWSTR /* szError */)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnStopBinding\n"));
return S_OK;
}

STDMETHOD(GetBindInfo)(DWORD* /* pgrfBINDF */, BINDINFO* /* pBindInfo */)
{
ATLTRACE(_T("IBindStatusCallbackImpl::GetBindInfo\n"));
return S_OK;
}

STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnDataAvailable\n"));
return S_OK;
}

STDMETHOD(OnObjectAvailable)(REFIID /* riid */, IUnknown* /* punk */)
{
ATLTRACE(_T("IBindStatusCallbackImpl::OnObjectAvailable\n"));
return S_OK;
}
};


template <class T>
class ATL_NO_VTABLE CBindStatusCallback :
public CComObjectRootEx<T::_ThreadModel::ThreadModelNoCS>,
public IBindStatusCallbackImpl<T>
{
typedef void (T::*ATL_PDATAAVAILABLE)(CBindStatusCallback<T>* pbsc, BYTE* pBytes, DWORD dwSize);

public:

BEGIN_COM_MAP(CBindStatusCallback<T>)
COM_INTERFACE_ENTRY_IID(IID_IBindStatusCallback, IBindStatusCallbackImpl<T>)
END_COM_MAP()


CBindStatusCallback()
{
m_pT = NULL;
m_pFunc = NULL;
}
~CBindStatusCallback()
{
ATLTRACE(_T("~CBindStatusCallback\n"));
}

STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pBinding)
{
ATLTRACE(_T("CBindStatusCallback::OnStartBinding\n"));
m_spBinding = pBinding;
return S_OK;
}

STDMETHOD(GetPriority)(LONG *pnPriority)
{
ATLTRACENOTIMPL(_T("CBindStatusCallback::GetPriority"));
}

STDMETHOD(OnLowResource)(DWORD reserved)
{
ATLTRACENOTIMPL(_T("CBindStatusCallback::OnLowResource"));
}

STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
{
ATLTRACENOTIMPL(_T("CBindStatusCallback::OnProgress"));
}

STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR szError)
{
ATLTRACE(_T("CBindStatusCallback::OnStopBinding\n"));
m_spBinding.Release();
return S_OK;
}

STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo)
{
ATLTRACE(_T("CBindStatusCallback::GetBindInfo\n"));
*pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
pbindInfo->cbSize = sizeof(BINDINFO);
pbindInfo->szExtraInfo = NULL;
memset(&pbindInfo->stgmedData, 0, sizeof(STGMEDIUM));
pbindInfo->grfBindInfoF = 0;
pbindInfo->dwBindVerb = BINDVERB_GET;
pbindInfo->szCustomVerb = NULL;
return S_OK;
}

STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
{
ATLTRACE(_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;
if (m_spStream)
m_spStream->AddRef();
}
}

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 S_FALSE;
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)
{
ATLTRACENOTIMPL(_T("CBindStatusCallback::OnObjectAvailable"));
}

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;
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, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(this)), 0, 0L);
else
m_spMoniker.Release();

if (SUCCEEDED(hr))
{
IStream* pStream;
hr = m_spMoniker->BindToStorage(m_spBindCtx, 0, IID_IStream, (void**)&pStream);
}
}
else
{
hr = CreateBindCtx(0, &m_spBindCtx);
if (SUCCEEDED(hr))
hr = RegisterBindStatusCallback(m_spBindCtx, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(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))
{
IStream* pStream;
hr = spBindHost->MonikerBindToStorage(m_spMoniker, NULL, reinterpret_cast<IBindStatusCallback*>(static_cast<IBindStatusCallbackImpl<T>*>(this)), IID_IStream, (void**)&pStream);
ATLTRACE(_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) \
{ \
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(); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(type* p##pname) \
{ \
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) \
{ \
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(); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(VARIANT_BOOL* p##pname) \
{ \
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) \
{ \
T* pT = (T*) this; \
if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
return S_FALSE; \
*(&(pT->m_##pname)) = SysAllocString(pname); \
pT->m_bRequiresSave = TRUE; \
pT->FireOnChanged(dispid); \
pT->FireViewChange(); \
return S_OK; \
} \
HRESULT STDMETHODCALLTYPE get_##fname(BSTR* p##pname) \
{ \
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)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_Font(IFontDisp* pFont)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_Font(IFontDisp** ppFont)
{
T* pT = (T*) this;
*ppFont = pT->m_pFont;
if (*ppFont != NULL)
(*ppFont)->AddRef();
return S_OK;
}
// Picture
HRESULT STDMETHODCALLTYPE put_Picture(IPictureDisp* pPicture)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_Picture(IPictureDisp* pPicture)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_Picture(IPictureDisp** ppPicture)
{
T* pT = (T*) this;
*ppPicture = pT->m_pPicture;
if (*ppPicture != NULL)
(*ppPicture)->AddRef();
return S_OK;
}
// MouseIcon
HRESULT STDMETHODCALLTYPE put_MouseIcon(IPictureDisp* pPicture)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE putref_MouseIcon(IPictureDisp* pPicture)
{
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();
return S_OK;
}
HRESULT STDMETHODCALLTYPE get_MouseIcon(IPictureDisp** ppPicture)
{
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*/)
{
return E_FAIL;
}
HRESULT STDMETHODCALLTYPE get_Window(long* phWnd)
{
T* pT = (T*) this;
*phWnd = (long)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(long, Appearance, nAppearance, DISPID_APPEARANCE)
IMPLEMENT_STOCKPROP(long, MousePointer, nMousePointer, DISPID_MOUSEPOINTER)
IMPLEMENT_STOCKPROP(long, ReadyState, nReadyState, DISPID_READYSTATE)
};

#ifndef ATL_NO_NAMESPACE
}; //namespace ATL
#endif

#endif // __ATLCTL_H__