home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / atl / include / atlctl.h < prev    next >
C/C++ Source or Header  |  1998-06-16  |  97KB  |  3,380 lines

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10.  
  11. #ifndef __ATLCTL_H__
  12. #define __ATLCTL_H__
  13.  
  14. #ifndef __cplusplus
  15.     #error ATL requires C++ compilation (use a .cpp suffix)
  16. #endif
  17.  
  18. #include <atlwin.h>
  19.  
  20. #include <objsafe.h>
  21. #include <urlmon.h>
  22.  
  23. #pragma comment(lib, "gdi32.lib")
  24. #pragma comment(lib, "urlmon.lib")
  25.  
  26.  
  27. #define DECLARE_VIEW_STATUS(statusFlags) \
  28.     DWORD _GetViewStatus() \
  29.     { \
  30.         return statusFlags; \
  31.     }
  32.  
  33. // Include GUIDs for the new stock property dialogs contained in the dll MSStkProp.DLL
  34. #include "msstkppg.h"
  35. #include "atliface.h"
  36. #define CLSID_MSStockFont CLSID_StockFontPage
  37. #define CLSID_MSStockColor CLSID_StockColorPage
  38. #define CLSID_MSStockPicture CLSID_StockPicturePage
  39.  
  40. struct ATL_DRAWINFO
  41. {
  42.     UINT cbSize;
  43.     DWORD dwDrawAspect;
  44.     LONG lindex;
  45.     DVTARGETDEVICE* ptd;
  46.     HDC hicTargetDev;
  47.     HDC hdcDraw;
  48.     LPCRECTL prcBounds; //Rectangle in which to draw
  49.     LPCRECTL prcWBounds; //WindowOrg and Ext if metafile
  50.     BOOL bOptimize;
  51.     BOOL bZoomed;
  52.     BOOL bRectInHimetric;
  53.     SIZEL ZoomNum;      //ZoomX = ZoomNum.cx/ZoomNum.cy
  54.     SIZEL ZoomDen;
  55. };
  56.  
  57. namespace ATL
  58. {
  59.  
  60. #pragma pack(push, _ATL_PACKING)
  61.  
  62. // Forward declarations
  63. //
  64. class ATL_NO_VTABLE CComControlBase;
  65. template <class T, class WinBase> class CComControl;
  66.  
  67. //////////////////////////////////////////////////////////////////////////////
  68. // CFirePropNotifyEvent
  69.  
  70.  
  71. // Helper functions for safely communicating with objects who sink IPropertyNotifySink
  72. class CFirePropNotifyEvent
  73. {
  74. public:
  75.     // Ask any objects sinking the IPropertyNotifySink notification if it is ok to edit a specified property
  76.     static HRESULT FireOnRequestEdit(IUnknown* pUnk, DISPID dispID)
  77.     {
  78.         CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  79.         if (!pCPC)
  80.             return S_OK;
  81.         CComPtr<IConnectionPoint> pCP;
  82.         pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  83.         if (!pCP)
  84.             return S_OK;
  85.         CComPtr<IEnumConnections> pEnum;
  86.  
  87.         if (FAILED(pCP->EnumConnections(&pEnum)))
  88.             return S_OK;
  89.         CONNECTDATA cd;
  90.         while (pEnum->Next(1, &cd, NULL) == S_OK)
  91.         {
  92.             if (cd.pUnk)
  93.             {
  94.                 HRESULT hr = S_OK;
  95.                 CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  96.                 if (pSink)
  97.                     hr = pSink->OnRequestEdit(dispID);
  98.                 cd.pUnk->Release();
  99.                 if (hr == S_FALSE)
  100.                     return S_FALSE;
  101.             }
  102.         }
  103.         return S_OK;
  104.     }
  105.     // Notify any objects sinking the IPropertyNotifySink notification that a property has changed
  106.     static HRESULT FireOnChanged(IUnknown* pUnk, DISPID dispID)
  107.     {
  108.         CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> pCPC(pUnk);
  109.         if (!pCPC)
  110.             return S_OK;
  111.         CComPtr<IConnectionPoint> pCP;
  112.         pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  113.         if (!pCP)
  114.             return S_OK;
  115.         CComPtr<IEnumConnections> pEnum;
  116.  
  117.         if (FAILED(pCP->EnumConnections(&pEnum)))
  118.             return S_OK;
  119.         CONNECTDATA cd;
  120.         while (pEnum->Next(1, &cd, NULL) == S_OK)
  121.         {
  122.             if (cd.pUnk)
  123.             {
  124.                 CComQIPtr<IPropertyNotifySink, &IID_IPropertyNotifySink> pSink(cd.pUnk);
  125.                 if (pSink)
  126.                     pSink->OnChanged(dispID);
  127.                 cd.pUnk->Release();
  128.             }
  129.         }
  130.         return S_OK;
  131.     }
  132. };
  133.  
  134.  
  135. //////////////////////////////////////////////////////////////////////////////
  136. // CComControlBase
  137.  
  138. // Holds the essential data members for an ActiveX control and useful helper functions
  139. class ATL_NO_VTABLE CComControlBase
  140. {
  141. public:
  142.     CComControlBase(HWND& h) : m_hWndCD(h)
  143.     {
  144.         memset(this, 0, sizeof(CComControlBase));
  145.         m_phWndCD = &h;
  146.         m_sizeExtent.cx = 2*2540;
  147.         m_sizeExtent.cy = 2*2540;
  148.         m_sizeNatural = m_sizeExtent;
  149.     }
  150.     ~CComControlBase()
  151.     {
  152.         if (m_hWndCD != NULL)
  153.             ::DestroyWindow(m_hWndCD);
  154.         ATLTRACE2(atlTraceControls,2,_T("Control Destroyed\n"));
  155.     }
  156.  
  157. // methods
  158. public:
  159.     // Control helper functions can go here non-virtuals only please
  160.  
  161.     // Mark the control 'dirty' so the container will save it
  162.     void SetDirty(BOOL bDirty)
  163.     {
  164.         m_bRequiresSave = bDirty;
  165.     }
  166.     // Obtain the dirty state for the control 
  167.     BOOL GetDirty()
  168.     {
  169.         return m_bRequiresSave ? TRUE : FALSE;
  170.     }
  171.     // Get the zoom factor (numerator & denominator) which is factor of the natural extent
  172.     void GetZoomInfo(ATL_DRAWINFO& di);
  173.     // Sends a notification that the moniker for the control has changed
  174.     HRESULT SendOnRename(IMoniker *pmk)
  175.     {
  176.         HRESULT hRes = S_OK;
  177.         if (m_spOleAdviseHolder)
  178.             hRes = m_spOleAdviseHolder->SendOnRename(pmk);
  179.         return hRes;
  180.     }
  181.     // Sends a notification that the control has just saved its data
  182.     HRESULT SendOnSave()
  183.     {
  184.         HRESULT hRes = S_OK;
  185.         if (m_spOleAdviseHolder)
  186.             hRes = m_spOleAdviseHolder->SendOnSave();
  187.         return hRes;
  188.     }
  189.     // Sends a notification that the control has closed its advisory sinks
  190.     HRESULT SendOnClose()
  191.     {
  192.         HRESULT hRes = S_OK;
  193.         if (m_spOleAdviseHolder)
  194.             hRes = m_spOleAdviseHolder->SendOnClose();
  195.         return hRes;
  196.     }
  197.     // Sends a notification that the control's data has changed
  198.     HRESULT SendOnDataChange(DWORD advf = 0);
  199.     // Sends a notification that the control's representation has changed
  200.     HRESULT SendOnViewChange(DWORD dwAspect, LONG lindex = -1)
  201.     {
  202.         if (m_spAdviseSink)
  203.             m_spAdviseSink->OnViewChange(dwAspect, lindex);
  204.         return S_OK;
  205.     }
  206.     // Sends a notification to the container that the control has received focus
  207.     LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  208.     {
  209.         if (m_bInPlaceActive)
  210.         {
  211.             CComPtr<IOleObject> pOleObject;
  212.             ControlQueryInterface(IID_IOleObject, (void**)&pOleObject);
  213.             if (pOleObject != NULL)
  214.                 pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_spClientSite, 0, m_hWndCD, &m_rcPos);
  215.             CComQIPtr<IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  216.             if (m_bInPlaceActive && spSite != NULL)
  217.                 spSite->OnFocus(TRUE);
  218.         }
  219.         bHandled = FALSE;
  220.         return 1;
  221.     }
  222.     LRESULT OnKillFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  223.     {
  224.         CComQIPtr<IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  225.         if (m_bInPlaceActive && spSite != NULL && !::IsChild(m_hWndCD, ::GetFocus()))
  226.             spSite->OnFocus(FALSE);
  227.         bHandled = FALSE;
  228.         return 1;
  229.     }
  230.     LRESULT OnMouseActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
  231.     {
  232.         BOOL bUserMode = TRUE;
  233.         HRESULT hRet = GetAmbientUserMode(bUserMode);
  234.         // UI activate if in user mode only
  235.         // allow activation if we can't determine mode
  236.         if (FAILED(hRet) || bUserMode)
  237.         {
  238.             CComPtr<IOleObject> pOleObject;
  239.             ControlQueryInterface(IID_IOleObject, (void**)&pOleObject);
  240.             if (pOleObject != NULL)
  241.                 pOleObject->DoVerb(OLEIVERB_UIACTIVATE, NULL, m_spClientSite, 0, m_hWndCD, &m_rcPos);
  242.         }
  243.         bHandled = FALSE;
  244.         return 1;
  245.     }
  246.     BOOL PreTranslateAccelerator(LPMSG /*pMsg*/, HRESULT& /*hRet*/)
  247.     {
  248.         return FALSE;
  249.     }
  250.  
  251.     HRESULT GetAmbientProperty(DISPID dispid, VARIANT& var)
  252.     {
  253.         HRESULT hRes = E_FAIL;
  254.         if (m_spAmbientDispatch.p != NULL)
  255.             hRes = m_spAmbientDispatch.GetProperty(dispid, &var);
  256.         return hRes;
  257.     }
  258.     HRESULT GetAmbientAppearance(short& nAppearance)
  259.     {
  260.         CComVariant var;
  261.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_APPEARANCE, var);
  262.         ATLASSERT(var.vt == VT_I2 || var.vt == VT_UI2 || var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
  263.         nAppearance = var.iVal;
  264.         return hRes;
  265.     }
  266.     HRESULT GetAmbientBackColor(OLE_COLOR& BackColor)
  267.     {
  268.         CComVariant var;
  269.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_BACKCOLOR, var);
  270.         ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
  271.         BackColor = var.lVal;
  272.         return hRes;
  273.     }
  274.     HRESULT GetAmbientDisplayName(BSTR& bstrDisplayName)
  275.     {
  276.         CComVariant var;
  277.         if (bstrDisplayName)
  278.         {
  279.             SysFreeString(bstrDisplayName);
  280.             bstrDisplayName = NULL;
  281.         }
  282.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYNAME, var);
  283.         if (SUCCEEDED(hRes))
  284.         {
  285.             if (var.vt != VT_BSTR)
  286.                 return E_FAIL;
  287.             bstrDisplayName = var.bstrVal;
  288.             var.vt = VT_EMPTY;
  289.             var.bstrVal = NULL;
  290.         }
  291.         return hRes;
  292.     }
  293.     HRESULT GetAmbientFont(IFont** ppFont)
  294.     {
  295.         // caller MUST Release the font!
  296.         if (ppFont == NULL)
  297.             return E_POINTER;
  298.         *ppFont = NULL;
  299.         CComVariant var;
  300.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FONT, var);
  301.         ATLASSERT((var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) || FAILED(hRes));
  302.         if (SUCCEEDED(hRes) && var.pdispVal)
  303.         {
  304.             if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  305.                 hRes = var.pdispVal->QueryInterface(IID_IFont, (void**)ppFont);
  306.             else
  307.                 hRes = DISP_E_BADVARTYPE;
  308.         }
  309.         return hRes;
  310.     }
  311.     HRESULT GetAmbientFontDisp(IFontDisp** ppFont)
  312.     {
  313.         // caller MUST Release the font!
  314.         if (ppFont == NULL)
  315.             return E_POINTER;
  316.         *ppFont = NULL;
  317.         CComVariant var;
  318.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FONT, var);
  319.         ATLASSERT((var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH) || FAILED(hRes));
  320.         if (SUCCEEDED(hRes) && var.pdispVal)
  321.         {
  322.             if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH)
  323.                 hRes = var.pdispVal->QueryInterface(IID_IFontDisp, (void**)ppFont);
  324.             else
  325.                 hRes = DISP_E_BADVARTYPE;
  326.         }
  327.         return hRes;
  328.     }
  329.     HRESULT GetAmbientForeColor(OLE_COLOR& ForeColor)
  330.     {
  331.         CComVariant var;
  332.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_FORECOLOR, var);
  333.         ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
  334.         ForeColor = var.lVal;
  335.         return hRes;
  336.     }
  337.     HRESULT GetAmbientLocaleID(LCID& lcid)
  338.     {
  339.         CComVariant var;
  340.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_LOCALEID, var);
  341.         ATLASSERT((var.vt == VT_UI4 || var.vt == VT_I4) || FAILED(hRes));
  342.         lcid = var.lVal;
  343.         return hRes;
  344.     }
  345.     HRESULT GetAmbientScaleUnits(BSTR& bstrScaleUnits)
  346.     {
  347.         CComVariant var;
  348.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SCALEUNITS, var);
  349.         ATLASSERT(var.vt == VT_BSTR || FAILED(hRes));
  350.         bstrScaleUnits = var.bstrVal;
  351.         return hRes;
  352.     }
  353.     HRESULT GetAmbientTextAlign(short& nTextAlign)
  354.     {
  355.         CComVariant var;
  356.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_TEXTALIGN, var);
  357.         ATLASSERT(var.vt == VT_I2 || FAILED(hRes));
  358.         nTextAlign = var.iVal;
  359.         return hRes;
  360.     }
  361.     HRESULT GetAmbientUserMode(BOOL& bUserMode)
  362.     {
  363.         CComVariant var;
  364.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
  365.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  366.         bUserMode = var.boolVal;
  367.         return hRes;
  368.     }
  369.     HRESULT GetAmbientUIDead(BOOL& bUIDead)
  370.     {
  371.         CComVariant var;
  372.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_UIDEAD, var);
  373.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  374.         bUIDead = var.boolVal;
  375.         return hRes;
  376.     }
  377.     HRESULT GetAmbientShowGrabHandles(BOOL& bShowGrabHandles)
  378.     {
  379.         CComVariant var;
  380.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWGRABHANDLES, var);
  381.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  382.         bShowGrabHandles = var.boolVal;
  383.         return hRes;
  384.     }
  385.     HRESULT GetAmbientShowHatching(BOOL& bShowHatching)
  386.     {
  387.         CComVariant var;
  388.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SHOWHATCHING, var);
  389.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  390.         bShowHatching = var.boolVal;
  391.         return hRes;
  392.     }
  393.     HRESULT GetAmbientMessageReflect(BOOL& bMessageReflect)
  394.     {
  395.         CComVariant var;
  396.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_MESSAGEREFLECT, var);
  397.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  398.         bMessageReflect = var.boolVal;
  399.         return hRes;
  400.     }
  401.     HRESULT GetAmbientAutoClip(BOOL& bAutoClip)
  402.     {
  403.         CComVariant var;
  404.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_AUTOCLIP, var);
  405.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  406.         bAutoClip = var.boolVal;
  407.         return hRes;
  408.     }
  409.     HRESULT GetAmbientDisplayAsDefault(BOOL& bDisplaysDefault)
  410.     {
  411.         CComVariant var;
  412.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_DISPLAYASDEFAULT, var);
  413.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  414.         bDisplaysDefault = var.boolVal;
  415.         return hRes;
  416.     }
  417.     HRESULT GetAmbientSupportsMnemonics(BOOL& bSupportMnemonics)
  418.     {
  419.         CComVariant var;
  420.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_SUPPORTSMNEMONICS, var);
  421.         ATLASSERT(var.vt == VT_BOOL || FAILED(hRes));
  422.         bSupportMnemonics = var.boolVal;
  423.         return hRes;
  424.     }
  425.     HRESULT GetAmbientPalette(HPALETTE& hPalette)
  426.     {
  427.         CComVariant var;
  428.         HRESULT hRes = GetAmbientProperty(DISPID_AMBIENT_PALETTE, var);
  429.         ATLASSERT(var.vt == VT_I4 || var.vt == VT_UI4 || FAILED(hRes));
  430.         hPalette = reinterpret_cast<HPALETTE>(var.lVal);
  431.         return hRes;
  432.     }
  433.  
  434.     HRESULT InternalGetSite(REFIID riid, void** ppUnkSite)
  435.     {
  436.         ATLASSERT(ppUnkSite != NULL);
  437.         if (ppUnkSite == NULL)
  438.             return E_POINTER;
  439.         if (m_spClientSite == NULL)
  440.         {
  441.             *ppUnkSite = NULL;
  442.             return S_OK;
  443.         }
  444.         return m_spClientSite->QueryInterface(riid, ppUnkSite);
  445.     }
  446.  
  447.     BOOL DoesVerbUIActivate(LONG iVerb)
  448.     {
  449.         BOOL b = FALSE;
  450.         switch (iVerb)
  451.         {
  452.             case OLEIVERB_UIACTIVATE:
  453.             case OLEIVERB_PRIMARY:
  454.                 b = TRUE;
  455.                 break;
  456.         }
  457.         // if no ambient dispatch then in old style OLE container
  458.         if (DoesVerbActivate(iVerb) && m_spAmbientDispatch.p == NULL)
  459.             b = TRUE;
  460.         return b;
  461.     }
  462.  
  463.     BOOL DoesVerbActivate(LONG iVerb)
  464.     {
  465.         BOOL b = FALSE;
  466.         switch (iVerb)
  467.         {
  468.             case OLEIVERB_UIACTIVATE:
  469.             case OLEIVERB_PRIMARY:
  470.             case OLEIVERB_SHOW:
  471.             case OLEIVERB_INPLACEACTIVATE:
  472.                 b = TRUE;
  473.                 break;
  474.         }
  475.         return b;
  476.     }
  477.  
  478.     BOOL SetControlFocus(BOOL bGrab);
  479.     HRESULT IQuickActivate_QuickActivate(QACONTAINER *pQACont,
  480.         QACONTROL *pQACtrl);
  481.     HRESULT DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent);
  482.     HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect = NULL);
  483.  
  484.     HRESULT IOleObject_SetClientSite(IOleClientSite *pClientSite);
  485.     HRESULT IOleObject_GetClientSite(IOleClientSite **ppClientSite);
  486.     HRESULT IOleObject_Advise(IAdviseSink *pAdvSink, DWORD *pdwConnection);
  487.     HRESULT IOleObject_Close(DWORD dwSaveOption);
  488.     HRESULT IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel);
  489.     HRESULT IOleInPlaceObject_InPlaceDeactivate(void);
  490.     HRESULT IOleInPlaceObject_UIDeactivate(void);
  491.     HRESULT IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip);
  492.     HRESULT IViewObject_Draw(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  493.         DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  494.         LPCRECTL prcBounds, LPCRECTL prcWBounds);
  495.     HRESULT IDataObject_GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium);
  496.  
  497.     HRESULT FireViewChange();
  498.     LRESULT OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& lResult);
  499.  
  500.     virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos) = 0;
  501.     virtual HRESULT ControlQueryInterface(const IID& iid, void** ppv) = 0;
  502.     virtual HRESULT OnDrawAdvanced(ATL_DRAWINFO& di);
  503.     virtual HRESULT OnDraw(ATL_DRAWINFO& /*di*/)
  504.     {
  505.         return S_OK;
  506.     }
  507.  
  508.  
  509. // Attributes
  510. public:
  511.     CComPtr<IOleInPlaceSiteWindowless> m_spInPlaceSite;
  512.     CComPtr<IDataAdviseHolder> m_spDataAdviseHolder;
  513.     CComPtr<IOleAdviseHolder> m_spOleAdviseHolder;
  514.     CComPtr<IOleClientSite> m_spClientSite;
  515.     CComPtr<IAdviseSink> m_spAdviseSink;
  516.     CComDispatchDriver m_spAmbientDispatch;
  517.  
  518.     SIZE m_sizeNatural; //unscaled size in himetric
  519.     SIZE m_sizeExtent;  //current extents in himetric
  520.     RECT m_rcPos; // position in pixels
  521. #pragma warning(disable: 4510 4610) // unnamed union
  522.     union
  523.     {
  524.         HWND& m_hWndCD;
  525.         HWND* m_phWndCD;
  526.     };
  527. #pragma warning(default: 4510 4610)
  528.     union
  529.     {
  530.         // m_nFreezeEvents is the only one actually used
  531.         int m_nFreezeEvents; // count of freezes versus thaws
  532.  
  533.         // These are here to make stock properties work
  534.         IPictureDisp* m_pMouseIcon;
  535.         IPictureDisp* m_pPicture;
  536.         IFontDisp* m_pFont;
  537.         OLE_COLOR m_clrBackColor;
  538.         OLE_COLOR m_clrBorderColor;
  539.         OLE_COLOR m_clrFillColor;
  540.         OLE_COLOR m_clrForeColor;
  541.         BSTR m_bstrText;
  542.         BSTR m_bstrCaption;
  543.         BOOL m_bValid;
  544.         BOOL m_bTabStop;
  545.         BOOL m_bBorderVisible;
  546.         BOOL m_bEnabled;
  547.         LONG m_nBackStyle;
  548.         LONG m_nBorderStyle;
  549.         LONG m_nBorderWidth;
  550.         LONG m_nDrawMode;
  551.         LONG m_nDrawStyle;
  552.         LONG m_nDrawWidth;
  553.         LONG m_nFillStyle;
  554.         SHORT m_nAppearance;
  555.         LONG m_nMousePointer;
  556.         LONG m_nReadyState;
  557.     };
  558.  
  559.     unsigned m_bNegotiatedWnd:1;
  560.     unsigned m_bWndLess:1;
  561.     unsigned m_bInPlaceActive:1;
  562.     unsigned m_bUIActive:1;
  563.     unsigned m_bUsingWindowRgn:1;
  564.     unsigned m_bInPlaceSiteEx:1;
  565.     unsigned m_bWindowOnly:1;
  566.     unsigned m_bRequiresSave:1;
  567.     unsigned m_bWasOnceWindowless:1;
  568.     unsigned m_bAutoSize:1; //SetExtent fails if size doesn't match existing
  569.     unsigned m_bRecomposeOnResize:1; //implies OLEMISC_RECOMPOSEONRESIZE
  570.     unsigned m_bResizeNatural:1;  //resize natural extent on SetExtent
  571.     unsigned m_bDrawFromNatural:1; //instead of m_sizeExtent
  572.     unsigned m_bDrawGetDataInHimetric:1; //instead of pixels
  573.  
  574.     DECLARE_VIEW_STATUS(VIEWSTATUS_OPAQUE)
  575. };
  576.  
  577. inline HRESULT CComControlBase::IQuickActivate_QuickActivate(QACONTAINER *pQACont,
  578.     QACONTROL *pQACtrl)
  579. {
  580.     ATLASSERT(pQACont != NULL);
  581.     ATLASSERT(pQACtrl != NULL);
  582.     if (!pQACont || !pQACtrl)
  583.         return E_POINTER;
  584.  
  585.     HRESULT hRes;
  586.     ULONG uCB = pQACtrl->cbSize;
  587.     memset(pQACtrl, 0, uCB);
  588.     pQACtrl->cbSize = uCB;
  589.  
  590.     // get all interfaces we are going to need
  591.     CComPtr<IOleObject> pOO;
  592.     ControlQueryInterface(IID_IOleObject, (void**)&pOO);
  593.     CComPtr<IViewObjectEx> pVOEX;
  594.     ControlQueryInterface(IID_IViewObjectEx, (void**)&pVOEX);
  595.     CComPtr<IPointerInactive> pPI;
  596.     ControlQueryInterface(IID_IPointerInactive, (void**)&pPI);
  597.     CComPtr<IProvideClassInfo2> pPCI;
  598.     ControlQueryInterface(IID_IProvideClassInfo2, (void**)&pPCI);
  599.  
  600.     if (pOO == NULL || pVOEX == NULL)
  601.         return E_FAIL;
  602.  
  603.     pOO->SetClientSite(pQACont->pClientSite);
  604.  
  605.     if (pQACont->pAdviseSink != NULL)
  606.     {
  607.         ATLTRACE2(atlTraceControls,2,_T("Setting up IOleObject Advise\n"));
  608.         pVOEX->SetAdvise(DVASPECT_CONTENT, 0, pQACont->pAdviseSink);
  609.     }
  610.  
  611.     CComPtr<IConnectionPointContainer> pCPC;
  612.     ControlQueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);
  613.  
  614.     if (pQACont->pPropertyNotifySink)
  615.     {
  616.         ATLTRACE2(atlTraceControls,2,_T("Setting up PropNotify CP\n"));
  617.         CComPtr<IConnectionPoint> pCP;
  618.         if (pCPC != NULL)
  619.         {
  620.             hRes = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP);
  621.             if (SUCCEEDED(hRes))
  622.                 pCP->Advise(pQACont->pPropertyNotifySink, &pQACtrl->dwPropNotifyCookie);
  623.         }
  624.     }
  625.  
  626.     if (pPCI)
  627.     {
  628.         GUID iidDefaultSrc;
  629.         if (SUCCEEDED(pPCI->GetGUID(GUIDKIND_DEFAULT_SOURCE_DISP_IID,
  630.             &iidDefaultSrc)))
  631.         {
  632.             if (pQACont->pUnkEventSink)
  633.             {
  634.                 ATLTRACE2(atlTraceControls,2,_T("Setting up Default Out Going Interface\n"));
  635.                 CComPtr<IConnectionPoint> pCP;
  636.                 if (pCPC != NULL)
  637.                 {
  638.                     hRes = pCPC->FindConnectionPoint(iidDefaultSrc, &pCP);
  639.                     if (SUCCEEDED(hRes))
  640.                         pCP->Advise(pQACont->pUnkEventSink, &pQACtrl->dwEventCookie);
  641.                 }
  642.             }
  643.         }
  644.     }
  645.     // give information to container
  646.     if (pOO != NULL)
  647.         pOO->GetMiscStatus(DVASPECT_CONTENT, &pQACtrl->dwMiscStatus);
  648.  
  649.     if (pVOEX != NULL)
  650.         pVOEX->GetViewStatus(&pQACtrl->dwViewStatus);
  651.  
  652.     if (pPI != NULL)
  653.         pPI->GetActivationPolicy(&pQACtrl->dwPointerActivationPolicy);
  654.     return S_OK;
  655. }
  656.  
  657. inline BOOL CComControlBase::SetControlFocus(BOOL bGrab)
  658. {
  659.     if (m_bWndLess)
  660.     {
  661.         if (!m_bUIActive && bGrab)
  662.             if (FAILED(InPlaceActivate(OLEIVERB_UIACTIVATE)))
  663.                 return FALSE;
  664.  
  665.         return (m_spInPlaceSite->SetFocus(bGrab) == S_OK);
  666.     }
  667.     else
  668.     {
  669.         // we've got a window.
  670.         //
  671.         if (m_bInPlaceActive)
  672.         {
  673.             HWND hwnd = (bGrab) ? m_hWndCD : ::GetParent(m_hWndCD);
  674.             if (!m_bUIActive && bGrab)
  675.                 return SUCCEEDED(InPlaceActivate(OLEIVERB_UIACTIVATE));
  676.             else
  677.             {
  678.                 if (!::IsChild(hwnd, ::GetFocus()))
  679.                     ::SetFocus(hwnd);
  680.                 return TRUE;
  681.             }
  682.         }
  683.     }
  684.     return FALSE;
  685. }
  686.  
  687. inline HRESULT CComControlBase::DoVerbProperties(LPCRECT /* prcPosRect */, HWND hwndParent)
  688. {
  689.     HRESULT hr = S_OK;
  690.     CComQIPtr <ISpecifyPropertyPages, &IID_ISpecifyPropertyPages> spPages;
  691.     CComQIPtr <IOleObject, &IID_IOleObject> spObj;
  692.     CComQIPtr <IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
  693.  
  694.     if (spSite)
  695.     {
  696.         hr = spSite->ShowPropertyFrame();
  697.         if (SUCCEEDED(hr))
  698.             return hr;
  699.     }
  700.  
  701.     CComPtr<IUnknown> pUnk;
  702.     ControlQueryInterface(IID_IUnknown, (void**)&pUnk);
  703.     ATLASSERT(pUnk != NULL);
  704.     CAUUID pages;
  705.     spPages = pUnk;
  706.     if (spPages)
  707.     {
  708.         hr = spPages->GetPages(&pages);
  709.         if (SUCCEEDED(hr))
  710.         {
  711.             spObj = pUnk;
  712.             if (spObj)
  713.             {
  714.                 LPOLESTR szTitle = NULL;
  715.  
  716.                 spObj->GetUserType(USERCLASSTYPE_SHORT, &szTitle);
  717.  
  718.                 LCID lcid;
  719.                 if (FAILED(GetAmbientLocaleID(lcid)))
  720.                     lcid = LOCALE_USER_DEFAULT;
  721.  
  722.                 hr = OleCreatePropertyFrame(hwndParent, m_rcPos.top, m_rcPos.left, szTitle,
  723.                     1, &pUnk.p, pages.cElems, pages.pElems, lcid, 0, 0);
  724.  
  725.                 CoTaskMemFree(szTitle);
  726.             }
  727.             else
  728.             {
  729.                 hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  730.             }
  731.             CoTaskMemFree(pages.pElems);
  732.         }
  733.     }
  734.     else
  735.     {
  736.         hr = OLEOBJ_S_CANNOT_DOVERB_NOW;
  737.     }
  738.  
  739.     return hr;
  740. }
  741.  
  742. inline HRESULT CComControlBase::InPlaceActivate(LONG iVerb, const RECT* /*prcPosRect*/)
  743. {
  744.     HRESULT hr;
  745.  
  746.     if (m_spClientSite == NULL)
  747.         return S_OK;
  748.  
  749.     CComPtr<IOleInPlaceObject> pIPO;
  750.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  751.     ATLASSERT(pIPO != NULL);
  752.  
  753.     if (!m_bNegotiatedWnd)
  754.     {
  755.         if (!m_bWindowOnly)
  756.             // Try for windowless site
  757.             hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
  758.  
  759.         if (m_spInPlaceSite)
  760.         {
  761.             m_bInPlaceSiteEx = TRUE;
  762.             // CanWindowlessActivate returns S_OK or S_FALSE
  763.             if ( m_spInPlaceSite->CanWindowlessActivate() == S_OK )
  764.             {
  765.                 m_bWndLess = TRUE;
  766.                 m_bWasOnceWindowless = TRUE;
  767.             }
  768.             else
  769.             {
  770.                 m_bWndLess = FALSE;
  771.             }
  772.         }
  773.         else
  774.         {
  775.             m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
  776.             if (m_spInPlaceSite)
  777.                 m_bInPlaceSiteEx = TRUE;
  778.             else
  779.                 hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
  780.         }
  781.     }
  782.  
  783.     ATLASSERT(m_spInPlaceSite);
  784.     if (!m_spInPlaceSite)
  785.         return E_FAIL;
  786.  
  787.     m_bNegotiatedWnd = TRUE;
  788.  
  789.     if (!m_bInPlaceActive)
  790.     {
  791.  
  792.         BOOL bNoRedraw = FALSE;
  793.         if (m_bWndLess)
  794.             m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
  795.         else
  796.         {
  797.             if (m_bInPlaceSiteEx)
  798.                 m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
  799.             else
  800.             {
  801.                 hr = m_spInPlaceSite->CanInPlaceActivate();
  802.                 // CanInPlaceActivate returns S_FALSE or S_OK
  803.                 if (FAILED(hr))
  804.                     return hr;
  805.                 if ( hr != S_OK )
  806.                 {
  807.                    // CanInPlaceActivate returned S_FALSE.
  808.                    return( E_FAIL );
  809.                 }
  810.                 m_spInPlaceSite->OnInPlaceActivate();
  811.             }
  812.         }
  813.     }
  814.  
  815.     m_bInPlaceActive = TRUE;
  816.  
  817.     // get location in the parent window,
  818.     // as well as some information about the parent
  819.     //
  820.     OLEINPLACEFRAMEINFO frameInfo;
  821.     RECT rcPos, rcClip;
  822.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  823.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  824.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  825.     HWND hwndParent;
  826.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  827.     {
  828.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  829.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  830.  
  831.         if (!m_bWndLess)
  832.         {
  833.             if (m_hWndCD)
  834.             {
  835.                 ShowWindow(m_hWndCD, SW_SHOW);
  836.                 if (!::IsChild(m_hWndCD, ::GetFocus()))
  837.                     ::SetFocus(m_hWndCD);
  838.             }
  839.             else
  840.             {
  841.                 HWND h = CreateControlWindow(hwndParent, rcPos);
  842.                 ATLASSERT(h != NULL);    // will assert if creation failed
  843.                 ATLASSERT(h == m_hWndCD);
  844.                 h;    // avoid unused warning
  845.             }
  846.         }
  847.  
  848.         pIPO->SetObjectRects(&rcPos, &rcClip);
  849.     }
  850.  
  851.     CComPtr<IOleInPlaceActiveObject> spActiveObject;
  852.     ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
  853.  
  854.     // Gone active by now, take care of UIACTIVATE
  855.     if (DoesVerbUIActivate(iVerb))
  856.     {
  857.         if (!m_bUIActive)
  858.         {
  859.             m_bUIActive = TRUE;
  860.             hr = m_spInPlaceSite->OnUIActivate();
  861.             if (FAILED(hr))
  862.                 return hr;
  863.  
  864.             SetControlFocus(TRUE);
  865.             // set ourselves up in the host.
  866.             //
  867.             if (spActiveObject)
  868.             {
  869.                 if (spInPlaceFrame)
  870.                     spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
  871.                 if (spInPlaceUIWindow)
  872.                     spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
  873.             }
  874.  
  875.             if (spInPlaceFrame)
  876.                 spInPlaceFrame->SetBorderSpace(NULL);
  877.             if (spInPlaceUIWindow)
  878.                 spInPlaceUIWindow->SetBorderSpace(NULL);
  879.         }
  880.     }
  881.  
  882.     m_spClientSite->ShowObject();
  883.  
  884.     return S_OK;
  885. }
  886.  
  887. inline HRESULT CComControlBase::SendOnDataChange(DWORD advf)
  888. {
  889.     HRESULT hRes = S_OK;
  890.     if (m_spDataAdviseHolder)
  891.     {
  892.         CComPtr<IDataObject> pdo;
  893.         if (SUCCEEDED(ControlQueryInterface(IID_IDataObject, (void**)&pdo)))
  894.             hRes = m_spDataAdviseHolder->SendOnDataChange(pdo, 0, advf);
  895.     }
  896.     return hRes;
  897. }
  898.  
  899. inline HRESULT CComControlBase::IOleObject_SetClientSite(IOleClientSite *pClientSite)
  900. {
  901.     ATLASSERT(pClientSite == NULL || m_spClientSite == NULL);
  902.     m_spClientSite = pClientSite;
  903.     m_spAmbientDispatch.Release();
  904.     if (m_spClientSite != NULL)
  905.     {
  906.         m_spClientSite->QueryInterface(IID_IDispatch,
  907.             (void**) &m_spAmbientDispatch.p);
  908.     }
  909.     return S_OK;
  910. }
  911.  
  912. inline HRESULT CComControlBase::IOleObject_GetClientSite(IOleClientSite **ppClientSite)
  913. {
  914.     ATLASSERT(ppClientSite);
  915.     if (ppClientSite == NULL)
  916.         return E_POINTER;
  917.  
  918.     *ppClientSite = m_spClientSite;
  919.     if (m_spClientSite != NULL)
  920.         m_spClientSite.p->AddRef();
  921.     return S_OK;
  922. }
  923.  
  924. inline HRESULT CComControlBase::IOleObject_Advise(IAdviseSink *pAdvSink,
  925.     DWORD *pdwConnection)
  926. {
  927.     HRESULT hr = S_OK;
  928.     if (m_spOleAdviseHolder == NULL)
  929.         hr = CreateOleAdviseHolder(&m_spOleAdviseHolder);
  930.     if (SUCCEEDED(hr))
  931.         hr = m_spOleAdviseHolder->Advise(pAdvSink, pdwConnection);
  932.     return hr;
  933. }
  934.  
  935. inline HRESULT CComControlBase::IOleObject_Close(DWORD dwSaveOption)
  936. {
  937.     CComPtr<IOleInPlaceObject> pIPO;
  938.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  939.     ATLASSERT(pIPO != NULL);
  940.     if (m_hWndCD)
  941.     {
  942.         if (m_spClientSite)
  943.             m_spClientSite->OnShowWindow(FALSE);
  944.     }
  945.  
  946.     if (m_bInPlaceActive)
  947.     {
  948.         HRESULT hr = pIPO->InPlaceDeactivate();
  949.         if (FAILED(hr))
  950.             return hr;
  951.         ATLASSERT(!m_bInPlaceActive);
  952.     }
  953.     if (m_hWndCD)
  954.     {
  955.         ATLTRACE2(atlTraceControls,2,_T("Destroying Window\n"));
  956.         if (::IsWindow(m_hWndCD))
  957.             DestroyWindow(m_hWndCD);
  958.         m_hWndCD = NULL;
  959.     }
  960.  
  961.     // handle the save flag.
  962.     //
  963.     if ((dwSaveOption == OLECLOSE_SAVEIFDIRTY ||
  964.         dwSaveOption == OLECLOSE_PROMPTSAVE) && m_bRequiresSave)
  965.     {
  966.         if (m_spClientSite)
  967.             m_spClientSite->SaveObject();
  968.         SendOnSave();
  969.     }
  970.  
  971.     m_spInPlaceSite.Release();
  972.     m_bNegotiatedWnd = FALSE;
  973.     m_bWndLess = FALSE;
  974.     m_bInPlaceSiteEx = FALSE;
  975.     m_spAdviseSink.Release();
  976.     return S_OK;
  977. }
  978.  
  979. inline HRESULT CComControlBase::IOleInPlaceObject_InPlaceDeactivate(void)
  980. {
  981.     CComPtr<IOleInPlaceObject> pIPO;
  982.     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
  983.     ATLASSERT(pIPO != NULL);
  984.  
  985.     if (!m_bInPlaceActive)
  986.         return S_OK;
  987.     pIPO->UIDeactivate();
  988.  
  989.     m_bInPlaceActive = FALSE;
  990.  
  991.     // if we have a window, tell it to go away.
  992.     //
  993.     if (m_hWndCD)
  994.     {
  995.         ATLTRACE2(atlTraceControls,2,_T("Destroying Window\n"));
  996.         if (::IsWindow(m_hWndCD))
  997.             DestroyWindow(m_hWndCD);
  998.         m_hWndCD = NULL;
  999.     }
  1000.  
  1001.     if (m_spInPlaceSite)
  1002.         m_spInPlaceSite->OnInPlaceDeactivate();
  1003.  
  1004.     return S_OK;
  1005. }
  1006.  
  1007. inline HRESULT CComControlBase::IOleInPlaceObject_UIDeactivate(void)
  1008. {
  1009.     // if we're not UIActive, not much to do.
  1010.     //
  1011.     if (!m_bUIActive)
  1012.         return S_OK;
  1013.  
  1014.     m_bUIActive = FALSE;
  1015.  
  1016.     // notify frame windows, if appropriate, that we're no longer ui-active.
  1017.     //
  1018.     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
  1019.     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
  1020.     OLEINPLACEFRAMEINFO frameInfo;
  1021.     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
  1022.     RECT rcPos, rcClip;
  1023.  
  1024.     HWND hwndParent; 
  1025.     // This call to GetWindow is a fix for Delphi
  1026.     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
  1027.     {
  1028.         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
  1029.             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
  1030.         if (spInPlaceUIWindow)
  1031.             spInPlaceUIWindow->SetActiveObject(NULL, NULL);
  1032.         if (spInPlaceFrame)
  1033.             spInPlaceFrame->SetActiveObject(NULL, NULL);
  1034.     }
  1035.     // we don't need to explicitly release the focus here since somebody
  1036.     // else grabbing the focus is what is likely to cause us to get lose it
  1037.     //
  1038.     m_spInPlaceSite->OnUIDeactivate(FALSE);
  1039.  
  1040.     return S_OK;
  1041. }
  1042.  
  1043. inline HRESULT CComControlBase::IOleInPlaceObject_SetObjectRects(LPCRECT prcPos,LPCRECT prcClip)
  1044. {
  1045.     if (prcPos == NULL || prcClip == NULL)
  1046.         return E_POINTER;
  1047.  
  1048.     m_rcPos = *prcPos;
  1049.     if (m_hWndCD)
  1050.     {
  1051.         // the container wants us to clip, so figure out if we really
  1052.         // need to
  1053.         //
  1054.         RECT rcIXect;
  1055.         BOOL b = IntersectRect(&rcIXect, prcPos, prcClip);
  1056.         HRGN tempRgn = NULL;
  1057.         if (b && !EqualRect(&rcIXect, prcPos))
  1058.         {
  1059.             OffsetRect(&rcIXect, -(prcPos->left), -(prcPos->top));
  1060.             tempRgn = CreateRectRgnIndirect(&rcIXect);
  1061.         }
  1062.  
  1063.         SetWindowRgn(m_hWndCD, tempRgn, TRUE);
  1064.  
  1065.         // set our control's location, but don't change it's size at all
  1066.         // [people for whom zooming is important should set that up here]
  1067.         //
  1068.         SIZEL size = {prcPos->right - prcPos->left, prcPos->bottom - prcPos->top};
  1069.         SetWindowPos(m_hWndCD, NULL, prcPos->left,
  1070.                      prcPos->top, size.cx, size.cy, SWP_NOZORDER | SWP_NOACTIVATE);
  1071.     }
  1072.  
  1073.     return S_OK;
  1074. }
  1075.  
  1076. inline HRESULT CComControlBase::IOleObject_SetExtent(DWORD dwDrawAspect, SIZEL *psizel)
  1077. {
  1078.     if (dwDrawAspect != DVASPECT_CONTENT)
  1079.         return DV_E_DVASPECT;
  1080.     if (psizel == NULL)
  1081.         return E_POINTER;
  1082.  
  1083.     BOOL bSizeMatchesNatural =
  1084.         memcmp(psizel, &m_sizeNatural, sizeof(SIZE)) == 0;
  1085.  
  1086.     if (m_bAutoSize) //object can't do any other size
  1087.         return (bSizeMatchesNatural) ? S_OK : E_FAIL;
  1088.  
  1089.     BOOL bResized = FALSE;
  1090.     if (memcmp(psizel, &m_sizeExtent, sizeof(SIZE)) != 0)
  1091.     {
  1092.         m_sizeExtent = *psizel;
  1093.         bResized = TRUE;
  1094.     }
  1095.     if (m_bResizeNatural && !bSizeMatchesNatural)
  1096.     {
  1097.         m_sizeNatural = *psizel;
  1098.         bResized = TRUE;
  1099.     }
  1100.  
  1101.     if (m_bRecomposeOnResize && bResized)
  1102.     {
  1103.         SendOnDataChange();
  1104.         FireViewChange();
  1105.     }
  1106.     return S_OK;
  1107. }
  1108.  
  1109. inline HRESULT CComControlBase::IViewObject_Draw(DWORD dwDrawAspect, LONG lindex,
  1110.     void *pvAspect, DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  1111.     LPCRECTL prcBounds, LPCRECTL prcWBounds)
  1112. {
  1113.     ATLTRACE2(atlTraceControls,2,_T("Draw dwDrawAspect=%x lindex=%d ptd=%x hic=%x hdc=%x\n"),
  1114.         dwDrawAspect, lindex, ptd, hicTargetDev, hdcDraw);
  1115. #ifdef _DEBUG
  1116.     if (prcBounds == NULL)
  1117.         ATLTRACE2(atlTraceControls,2,_T("\tprcBounds=NULL\n"));
  1118.     else
  1119.         ATLTRACE2(atlTraceControls,2,_T("\tprcBounds=%d,%d,%d,%d\n"), prcBounds->left,
  1120.             prcBounds->top, prcBounds->right, prcBounds->bottom);
  1121.     if (prcWBounds == NULL)
  1122.         ATLTRACE2(atlTraceControls,2,_T("\tprcWBounds=NULL\n"));
  1123.     else
  1124.         ATLTRACE2(atlTraceControls,2,_T("\tprcWBounds=%d,%d,%d,%d\n"), prcWBounds->left,
  1125.             prcWBounds->top, prcWBounds->right, prcWBounds->bottom);
  1126. #endif
  1127.  
  1128.     if (prcBounds == NULL)
  1129.     {
  1130.         if (!m_bWndLess)
  1131.             return E_INVALIDARG;
  1132.         prcBounds = (RECTL*)&m_rcPos;
  1133.     }
  1134.  
  1135.     // support the aspects required for multi-pass drawing
  1136.     switch (dwDrawAspect)
  1137.     {
  1138.         case DVASPECT_CONTENT:
  1139.         case DVASPECT_OPAQUE:
  1140.         case DVASPECT_TRANSPARENT:
  1141.             break;
  1142.         default:
  1143.             ATLASSERT(FALSE);
  1144.             return DV_E_DVASPECT;
  1145.             break;
  1146.     }
  1147.  
  1148.     // make sure nobody forgets to do this
  1149.     if (ptd == NULL)
  1150.         hicTargetDev = NULL;
  1151.  
  1152.     BOOL bOptimize = FALSE;
  1153.     if (pvAspect && ((DVASPECTINFO *)pvAspect)->cb >= sizeof(DVASPECTINFO))
  1154.         bOptimize = (((DVASPECTINFO *)pvAspect)->dwFlags & DVASPECTINFOFLAG_CANOPTIMIZE);
  1155.  
  1156.     ATL_DRAWINFO di;
  1157.     memset(&di, 0, sizeof(di));
  1158.     di.cbSize = sizeof(di);
  1159.     di.dwDrawAspect = dwDrawAspect;
  1160.     di.lindex = lindex;
  1161.     di.ptd = ptd;
  1162.     di.hicTargetDev = hicTargetDev;
  1163.     di.hdcDraw = hdcDraw;
  1164.     di.prcBounds = prcBounds;
  1165.     di.prcWBounds = prcWBounds;
  1166.     di.bOptimize = bOptimize;
  1167.     return OnDrawAdvanced(di);
  1168. }
  1169.  
  1170. inline HRESULT CComControlBase::IDataObject_GetData(FORMATETC *pformatetcIn,
  1171.     STGMEDIUM *pmedium)
  1172. {
  1173.     if (pmedium == NULL)
  1174.         return E_POINTER;
  1175.     memset(pmedium, 0, sizeof(STGMEDIUM));
  1176.     ATLTRACE2(atlTraceControls,2,_T("Format = %x\n"), pformatetcIn->cfFormat);
  1177.     ATLTRACE2(atlTraceControls,2,_T("TYMED = %x\n"), pformatetcIn->tymed);
  1178.  
  1179.     if ((pformatetcIn->tymed & TYMED_MFPICT) == 0)
  1180.         return DATA_E_FORMATETC;
  1181.  
  1182.     SIZEL sizeMetric, size;
  1183.     if (m_bDrawFromNatural)
  1184.         sizeMetric = m_sizeNatural;
  1185.     else
  1186.         sizeMetric = m_sizeExtent;
  1187.     if (!m_bDrawGetDataInHimetric)
  1188.         AtlHiMetricToPixel(&sizeMetric, &size);
  1189.     else
  1190.         size = sizeMetric;
  1191.     RECTL rectl = {0 ,0, size.cx, size.cy};
  1192.  
  1193.     ATL_DRAWINFO di;
  1194.     memset(&di, 0, sizeof(di));
  1195.     di.cbSize = sizeof(di);
  1196.     di.dwDrawAspect = DVASPECT_CONTENT;
  1197.     di.lindex = -1;
  1198.     di.ptd = NULL;
  1199.     di.hicTargetDev = NULL;
  1200.     di.prcBounds = &rectl;
  1201.     di.prcWBounds = &rectl;
  1202.     di.bOptimize = TRUE; //we do a SaveDC/RestoreDC
  1203.     di.bRectInHimetric = m_bDrawGetDataInHimetric;
  1204.     // create appropriate memory metafile DC
  1205.     di.hdcDraw = CreateMetaFile(NULL);
  1206.  
  1207.     // create attribute DC according to pformatetcIn->ptd
  1208.  
  1209.     SaveDC(di.hdcDraw);
  1210.     SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  1211.     SetWindowExtEx(di.hdcDraw, rectl.right, rectl.bottom, NULL);
  1212.     OnDrawAdvanced(di);
  1213.     RestoreDC(di.hdcDraw, -1);
  1214.  
  1215.     HMETAFILE hMF = CloseMetaFile(di.hdcDraw);
  1216.     if (hMF == NULL)
  1217.         return E_UNEXPECTED;
  1218.  
  1219.     HGLOBAL hMem=GlobalAlloc(GMEM_SHARE | GMEM_MOVEABLE, sizeof(METAFILEPICT));
  1220.  
  1221.     if (NULL==hMem)
  1222.     {
  1223.         DeleteMetaFile(hMF);
  1224.         return ResultFromScode(STG_E_MEDIUMFULL);
  1225.     }
  1226.  
  1227.     LPMETAFILEPICT pMF=(LPMETAFILEPICT)GlobalLock(hMem);
  1228.     pMF->hMF=hMF;
  1229.     pMF->mm=MM_ANISOTROPIC;
  1230.     pMF->xExt=sizeMetric.cx;
  1231.     pMF->yExt=sizeMetric.cy;
  1232.     GlobalUnlock(hMem);
  1233.  
  1234.     pmedium->tymed = TYMED_MFPICT;
  1235.     pmedium->hGlobal = hMem;
  1236.     pmedium->pUnkForRelease = NULL;
  1237.  
  1238.     return S_OK;
  1239. }
  1240.  
  1241. inline HRESULT CComControlBase::FireViewChange()
  1242. {
  1243.     if (m_bInPlaceActive)
  1244.     {
  1245.         // Active
  1246.         if (m_hWndCD != NULL)
  1247.             ::InvalidateRect(m_hWndCD, NULL, TRUE); // Window based
  1248.         else if (m_spInPlaceSite != NULL)
  1249.             m_spInPlaceSite->InvalidateRect(NULL, TRUE); // Windowless
  1250.     }
  1251.     else // Inactive
  1252.         SendOnViewChange(DVASPECT_CONTENT);
  1253.     return S_OK;
  1254. }
  1255.  
  1256. inline void CComControlBase::GetZoomInfo(ATL_DRAWINFO& di)
  1257. {
  1258.     const RECTL& rcPos = *di.prcBounds;
  1259.     SIZEL sizeDen;
  1260.     if (m_bDrawFromNatural)
  1261.         sizeDen = m_sizeNatural;
  1262.     else
  1263.         sizeDen = m_sizeExtent;
  1264.     if (!di.bRectInHimetric)
  1265.         AtlHiMetricToPixel(&sizeDen, &sizeDen);
  1266.     SIZEL sizeNum = {rcPos.right-rcPos.left, rcPos.bottom-rcPos.top};
  1267.     di.ZoomNum.cx = sizeNum.cx;
  1268.     di.ZoomNum.cy = sizeNum.cy;
  1269.     di.ZoomDen.cx = sizeDen.cx;
  1270.     di.ZoomDen.cy = sizeDen.cy;
  1271.     if (sizeDen.cx == 0 || sizeDen.cy == 0 ||
  1272.         sizeNum.cx == 0 || sizeNum.cy == 0)
  1273.     {
  1274.         di.ZoomNum.cx = di.ZoomNum.cy = di.ZoomDen.cx = di.ZoomDen.cy = 1;
  1275.         di.bZoomed = FALSE;
  1276.     }
  1277.     else if (sizeNum.cx != sizeDen.cx || sizeNum.cy != sizeDen.cy)
  1278.         di.bZoomed = TRUE;
  1279.     else
  1280.         di.bZoomed = FALSE;
  1281. }
  1282.  
  1283. inline HRESULT CComControlBase::OnDrawAdvanced(ATL_DRAWINFO& di)
  1284. {
  1285.     BOOL bDeleteDC = FALSE;
  1286.     if (di.hicTargetDev == NULL)
  1287.     {
  1288.         di.hicTargetDev = AtlCreateTargetDC(di.hdcDraw, di.ptd);
  1289.         bDeleteDC = (di.hicTargetDev != di.hdcDraw);
  1290.     }
  1291.     RECTL rectBoundsDP = *di.prcBounds;
  1292.     BOOL bMetafile = GetDeviceCaps(di.hdcDraw, TECHNOLOGY) == DT_METAFILE;
  1293.     if (!bMetafile)
  1294.     {
  1295.         ::LPtoDP(di.hicTargetDev, (LPPOINT)&rectBoundsDP, 2);
  1296.         SaveDC(di.hdcDraw);
  1297.         SetMapMode(di.hdcDraw, MM_TEXT);
  1298.         SetWindowOrgEx(di.hdcDraw, 0, 0, NULL);
  1299.         SetViewportOrgEx(di.hdcDraw, 0, 0, NULL);
  1300.         di.bOptimize = TRUE; //since we save the DC we can do this
  1301.     }
  1302.     di.prcBounds = &rectBoundsDP;
  1303.     GetZoomInfo(di);
  1304.  
  1305.     HRESULT hRes = OnDraw(di);
  1306.     if (bDeleteDC)
  1307.         ::DeleteDC(di.hicTargetDev);
  1308.     if (!bMetafile)
  1309.         RestoreDC(di.hdcDraw, -1);
  1310.     return hRes;
  1311. }
  1312.  
  1313. inline LRESULT CComControlBase::OnPaint(UINT /* uMsg */, WPARAM wParam,
  1314.     LPARAM /* lParam */, BOOL& /* lResult */)
  1315. {
  1316.     RECT rc;
  1317.     PAINTSTRUCT ps;
  1318.  
  1319.     HDC hdc = (wParam != NULL) ? (HDC)wParam : ::BeginPaint(m_hWndCD, &ps);
  1320.     if (hdc == NULL)
  1321.         return 0;
  1322.     ::GetClientRect(m_hWndCD, &rc);
  1323.  
  1324.     ATL_DRAWINFO di;
  1325.     memset(&di, 0, sizeof(di));
  1326.     di.cbSize = sizeof(di);
  1327.     di.dwDrawAspect = DVASPECT_CONTENT;
  1328.     di.lindex = -1;
  1329.     di.hdcDraw = hdc;
  1330.     di.prcBounds = (LPCRECTL)&rc;
  1331.  
  1332.     OnDrawAdvanced(di);
  1333.     if (wParam == NULL)
  1334.         ::EndPaint(m_hWndCD, &ps);
  1335.     return 0;
  1336. }
  1337.  
  1338. template <class T, class WinBase =  CWindowImpl< T > >
  1339. class ATL_NO_VTABLE CComControl :  public CComControlBase, public WinBase
  1340. {
  1341. public:
  1342.     CComControl() : CComControlBase(m_hWnd) {}
  1343.     HRESULT FireOnRequestEdit(DISPID dispID)
  1344.     {
  1345.         T* pT = static_cast<T*>(this);
  1346.         return T::__ATL_PROP_NOTIFY_EVENT_CLASS::FireOnRequestEdit(pT->GetUnknown(), dispID);
  1347.     }
  1348.     HRESULT FireOnChanged(DISPID dispID)
  1349.     {
  1350.         T* pT = static_cast<T*>(this);
  1351.         return T::__ATL_PROP_NOTIFY_EVENT_CLASS::FireOnChanged(pT->GetUnknown(), dispID);
  1352.     }
  1353.     virtual HRESULT ControlQueryInterface(const IID& iid, void** ppv)
  1354.     {
  1355.         T* pT = static_cast<T*>(this);
  1356.         return pT->_InternalQueryInterface(iid, ppv);
  1357.     }
  1358.     virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos)
  1359.     {
  1360.         T* pT = static_cast<T*>(this);
  1361.         return pT->Create(hWndParent, rcPos);
  1362.     }
  1363.  
  1364.     typedef CComControl< T, WinBase >    thisClass;
  1365.     BEGIN_MSG_MAP(thisClass)
  1366.         MESSAGE_HANDLER(WM_PAINT, CComControlBase::OnPaint)
  1367.         MESSAGE_HANDLER(WM_SETFOCUS, CComControlBase::OnSetFocus)
  1368.         MESSAGE_HANDLER(WM_KILLFOCUS, CComControlBase::OnKillFocus)
  1369.         MESSAGE_HANDLER(WM_MOUSEACTIVATE, CComControlBase::OnMouseActivate)
  1370.     END_MSG_MAP()
  1371. };
  1372.  
  1373. //////////////////////////////////////////////////////////////////////////////
  1374. // CComCompositeControl
  1375.  
  1376. #ifndef _ATL_NO_HOSTING
  1377. template <class T>
  1378. class CComCompositeControl : public CComControl< T, CAxDialogImpl< T > >
  1379. {
  1380. public:
  1381.     CComCompositeControl()
  1382.     {
  1383.         m_hbrBackground = NULL;
  1384.     }
  1385.     ~CComCompositeControl()
  1386.     {
  1387.         DeleteObject(m_hbrBackground);
  1388.     }
  1389.     HRESULT AdviseSinkMap(bool bAdvise)
  1390.     {
  1391.         if(!bAdvise && m_hWnd == NULL)
  1392.         {
  1393.             // window is gone, controls are already unadvised
  1394.             ATLTRACE2(atlTraceControls, 1, _T("CComCompositeControl::AdviseSinkMap called after the window was destroyed\n"));
  1395.             return S_OK;
  1396.         }
  1397.         T* pT = static_cast<T*>(this);
  1398.         return AtlAdviseSinkMap(pT, bAdvise);
  1399.     }
  1400.     HBRUSH m_hbrBackground;
  1401.     HRESULT SetBackgroundColorFromAmbient()
  1402.     {
  1403.         if (m_hbrBackground != NULL)
  1404.         {
  1405.             DeleteObject(m_hbrBackground);
  1406.             m_hbrBackground = NULL;
  1407.         }
  1408.         OLE_COLOR clr;
  1409.         HRESULT hr = GetAmbientBackColor(clr);
  1410.         if (SUCCEEDED(hr))
  1411.         {
  1412.             COLORREF rgb;
  1413.             ::OleTranslateColor(clr, NULL, &rgb);
  1414.             m_hbrBackground = ::CreateSolidBrush(rgb);
  1415.             EnumChildWindows(m_hWnd, (WNDENUMPROC)BackgroundColorEnumProc, (LPARAM) clr);
  1416.         }
  1417.         return hr;
  1418.     }
  1419.     static BOOL CALLBACK BackgroundColorEnumProc(HWND hwnd, LPARAM l)
  1420.     {
  1421.         CAxWindow wnd(hwnd);
  1422.         CComPtr<IAxWinAmbientDispatch> spDispatch;
  1423.         wnd.QueryHost(&spDispatch);
  1424.         if (spDispatch != NULL)
  1425.             spDispatch->put_BackColor((OLE_COLOR)l);
  1426.         return TRUE;
  1427.     }
  1428.     LRESULT OnDialogColor(UINT, WPARAM w, LPARAM, BOOL&)
  1429.     {
  1430.         HDC dc = (HDC) w;
  1431.         LOGBRUSH lb;
  1432.         ::GetObject(m_hbrBackground, sizeof(lb), (void*)&lb);
  1433.         ::SetBkColor(dc, lb.lbColor);
  1434.         return (LRESULT)m_hbrBackground;
  1435.     }
  1436.     HWND Create(HWND hWndParent, RECT& /*rcPos*/, LPARAM dwInitParam = NULL)
  1437.     {
  1438.         CComControl< T, CAxDialogImpl< T > >::Create(hWndParent, dwInitParam);
  1439.         SetBackgroundColorFromAmbient();
  1440.         if (m_hWnd != NULL)
  1441.             ShowWindow(SW_SHOWNOACTIVATE);
  1442.         return m_hWnd;
  1443.     }
  1444.     BOOL CalcExtent(SIZE& size)
  1445.     {
  1446.         HINSTANCE hInstance = _Module.GetResourceInstance();
  1447.         LPCTSTR lpTemplateName = MAKEINTRESOURCE(T::IDD);
  1448.         HRSRC hDlgTempl = FindResource(hInstance, lpTemplateName, RT_DIALOG);
  1449.         if (hDlgTempl == NULL)
  1450.             return FALSE;
  1451.         HGLOBAL hResource = LoadResource(hInstance, hDlgTempl);
  1452.         DLGTEMPLATE* pDlgTempl = (DLGTEMPLATE*)LockResource(hResource);
  1453.         if (pDlgTempl == NULL)
  1454.             return FALSE;
  1455.         AtlGetDialogSize(pDlgTempl, &size);
  1456.         AtlPixelToHiMetric(&size, &size);
  1457.         return TRUE;
  1458.     }
  1459. //Implementation
  1460.     BOOL PreTranslateAccelerator(LPMSG pMsg, HRESULT& hRet)
  1461.     {
  1462.         hRet = S_OK;
  1463.         if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
  1464.            (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
  1465.             return FALSE;
  1466.         // find a direct child of the dialog from the window that has focus
  1467.         HWND hWndCtl = ::GetFocus();
  1468.         if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd)
  1469.         {
  1470.             do
  1471.             {
  1472.                 hWndCtl = ::GetParent(hWndCtl);
  1473.             }
  1474.             while (::GetParent(hWndCtl) != m_hWnd);
  1475.         }
  1476.         // give controls a chance to translate this message
  1477.         if (::SendMessage(hWndCtl, WM_FORWARDMSG, 0, (LPARAM)pMsg) == 1)
  1478.             return TRUE;
  1479.  
  1480.         // special handling for keyboard messages
  1481.         DWORD dwDlgCode = ::SendMessage(pMsg->hwnd, WM_GETDLGCODE, 0, 0L);
  1482.         switch(pMsg->message)
  1483.         {
  1484.         case WM_CHAR:
  1485.             if(dwDlgCode == 0)    // no dlgcode, possibly an ActiveX control
  1486.                 return FALSE;    // let the container process this
  1487.             break;
  1488.         case WM_KEYDOWN:
  1489.             switch(LOWORD(pMsg->wParam))
  1490.             {
  1491.             case VK_TAB:
  1492.                 // prevent tab from looping inside of our dialog
  1493.                 if((dwDlgCode & DLGC_WANTTAB) == 0)
  1494.                 {
  1495.                     HWND hWndFirstOrLast = ::GetWindow(m_hWnd, GW_CHILD);
  1496.                     if (::GetKeyState(VK_SHIFT) >= 0)  // not pressed
  1497.                         hWndFirstOrLast = GetNextDlgTabItem(hWndFirstOrLast, TRUE);
  1498.                     if (hWndFirstOrLast == hWndCtl)
  1499.                         return FALSE;
  1500.                 }
  1501.                 break;
  1502.             case VK_LEFT:
  1503.             case VK_UP:
  1504.             case VK_RIGHT:
  1505.             case VK_DOWN:
  1506.                 // prevent arrows from looping inside of our dialog
  1507.                 if((dwDlgCode & DLGC_WANTARROWS) == 0)
  1508.                 {
  1509.                     HWND hWndFirstOrLast = ::GetWindow(m_hWnd, GW_CHILD);
  1510.                     if (pMsg->wParam == VK_RIGHT || pMsg->wParam == VK_DOWN)    // going forward
  1511.                         hWndFirstOrLast = GetNextDlgTabItem(hWndFirstOrLast, TRUE);
  1512.                     if (hWndFirstOrLast == hWndCtl)
  1513.                         return FALSE;
  1514.                 }
  1515.                 break;
  1516.             case VK_EXECUTE:
  1517.             case VK_RETURN:
  1518.             case VK_ESCAPE:
  1519.             case VK_CANCEL:
  1520.                 // we don't want to handle these, let the container do it
  1521.                 return FALSE;
  1522.             }
  1523.             break;
  1524.         }
  1525.  
  1526.         return IsDialogMessage(pMsg);
  1527.     }
  1528.     HRESULT IOleInPlaceObject_InPlaceDeactivate(void)
  1529.     {
  1530.         AdviseSinkMap(false); //unadvise
  1531.         return CComControl<T, CAxDialogImpl<T> >::IOleInPlaceObject_InPlaceDeactivate();
  1532.     }
  1533.     virtual HWND CreateControlWindow(HWND hWndParent, RECT& rcPos)
  1534.     {
  1535.         T* pT = static_cast<T*>(this);
  1536.         HWND h = pT->Create(hWndParent, rcPos);
  1537.         if (h != NULL)
  1538.             AdviseSinkMap(true);
  1539.         return h;
  1540.     }
  1541.     virtual HRESULT OnDraw(ATL_DRAWINFO& di)
  1542.     {
  1543.         if(!m_bInPlaceActive)
  1544.         {
  1545.             HPEN hPen = (HPEN)::GetStockObject(BLACK_PEN);
  1546.             HBRUSH hBrush = (HBRUSH)::GetStockObject(GRAY_BRUSH);
  1547.             ::SelectObject(di.hdcDraw, hPen);
  1548.             ::SelectObject(di.hdcDraw, hBrush);
  1549.             ::Rectangle(di.hdcDraw, di.prcBounds->left, di.prcBounds->top, di.prcBounds->right, di.prcBounds->bottom);
  1550.             ::SetTextColor(di.hdcDraw, ::GetSysColor(COLOR_WINDOWTEXT));
  1551.             ::SetBkMode(di.hdcDraw, TRANSPARENT);
  1552.             ::DrawText(di.hdcDraw, _T("ATL Composite Control"), -1, (LPRECT)di.prcBounds, DT_CENTER | DT_SINGLELINE | DT_VCENTER);
  1553.         }
  1554.         return S_OK;
  1555.     }
  1556.     typedef CComControl< T, CAxDialogImpl< T > >    baseClass;
  1557.     BEGIN_MSG_MAP(CComCompositeControl< T >)
  1558.         MESSAGE_HANDLER(WM_CTLCOLORDLG, OnDialogColor)
  1559.         MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnDialogColor)
  1560.         MESSAGE_HANDLER(WM_SETFOCUS, baseClass::OnSetFocus)
  1561.         MESSAGE_HANDLER(WM_KILLFOCUS, baseClass::OnKillFocus)
  1562.         MESSAGE_HANDLER(WM_MOUSEACTIVATE, baseClass::OnMouseActivate)
  1563.     END_MSG_MAP()
  1564.  
  1565.     BEGIN_SINK_MAP(T)
  1566.     END_SINK_MAP()
  1567. };
  1568. #endif //_ATL_NO_HOSTING
  1569.  
  1570. // Forward declarations
  1571. //
  1572. template <class T> class IPersistStorageImpl;
  1573. template <class T> class IPersistPropertyBagImpl;
  1574.  
  1575. template <class T> class IOleControlImpl;
  1576. template <class T> class IRunnableObjectImpl;
  1577. template <class T> class IQuickActivateImpl;
  1578. template <class T> class IOleObjectImpl;
  1579. template <class T> class IPropertyPageImpl;
  1580. template <class T> class IPropertyPage2Impl;
  1581. template <class T> class IPerPropertyBrowsingImpl;
  1582. template <class T> class IViewObjectExImpl;
  1583. template <class T> class IOleWindowImpl;
  1584. template <class T> class IPointerInactiveImpl;
  1585. template <class T, class CDV> class IPropertyNotifySinkCP;
  1586. template <class T> class IBindStatusCallbackImpl;
  1587. template <class T> class CBindStatusCallback;
  1588.  
  1589.  
  1590. //////////////////////////////////////////////////////////////////////////////
  1591. // IOleControlImpl
  1592. template <class T>
  1593. class ATL_NO_VTABLE IOleControlImpl : public IOleControl
  1594. {
  1595. public:
  1596.     STDMETHOD(GetControlInfo)(LPCONTROLINFO /* pCI */)
  1597.     {
  1598.         ATLTRACENOTIMPL(_T("IOleControlImpl::GetControlInfo"));
  1599.     }
  1600.     STDMETHOD(OnMnemonic)(LPMSG /* pMsg */)
  1601.     {
  1602.         ATLTRACENOTIMPL(_T("IOleControlImpl::OnMnemonic"));
  1603.     }
  1604.     STDMETHOD(OnAmbientPropertyChange)(DISPID dispid)
  1605.     {
  1606.         dispid;
  1607.         ATLTRACE2(atlTraceControls,2,_T("IOleControlImpl::OnAmbientPropertyChange\n"));
  1608.         ATLTRACE2(atlTraceControls,2,_T(" -- DISPID = %d (%d)\n"), dispid);
  1609.         return S_OK;
  1610.     }
  1611.     STDMETHOD(FreezeEvents)(BOOL bFreeze)
  1612.     {
  1613.         T* pT = static_cast<T*>(this);
  1614.         ATLTRACE2(atlTraceControls,2,_T("IOleControlImpl::FreezeEvents\n"));
  1615.         if (bFreeze)
  1616.             pT->m_nFreezeEvents++;
  1617.         else
  1618.             pT->m_nFreezeEvents--;
  1619.         return S_OK;
  1620.     }
  1621. };
  1622.  
  1623.  
  1624. //////////////////////////////////////////////////////////////////////////////
  1625. // IQuickActivateImpl
  1626. template <class T>
  1627. class ATL_NO_VTABLE IQuickActivateImpl : public IQuickActivate
  1628. {
  1629. public:
  1630.     STDMETHOD(QuickActivate)(QACONTAINER *pQACont, QACONTROL *pQACtrl)
  1631.     {
  1632.         T* pT = static_cast<T*>(this);
  1633.         ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::QuickActivate\n"));
  1634.         return pT->IQuickActivate_QuickActivate(pQACont, pQACtrl);
  1635.     }
  1636.     STDMETHOD(SetContentExtent)(LPSIZEL pSize)
  1637.     {
  1638.         T* pT = static_cast<T*>(this);
  1639.         ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::SetContentExtent\n"));
  1640.         return pT->IOleObjectImpl<T>::SetExtent(DVASPECT_CONTENT, pSize);
  1641.     }
  1642.     STDMETHOD(GetContentExtent)(LPSIZEL pSize)
  1643.     {
  1644.         T* pT = static_cast<T*>(this);
  1645.         ATLTRACE2(atlTraceControls,2,_T("IQuickActivateImpl::GetContentExtent\n"));
  1646.         return pT->IOleObjectImpl<T>::GetExtent(DVASPECT_CONTENT, pSize);
  1647.     }
  1648. };
  1649.  
  1650.  
  1651. //////////////////////////////////////////////////////////////////////////////
  1652. // IOleObjectImpl
  1653. template <class T>
  1654. class ATL_NO_VTABLE IOleObjectImpl : public IOleObject
  1655. {
  1656. public:
  1657.     STDMETHOD(SetClientSite)(IOleClientSite *pClientSite)
  1658.     {
  1659.         T* pT = static_cast<T*>(this);
  1660.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetClientSite\n"));
  1661.         return pT->IOleObject_SetClientSite(pClientSite);
  1662.     }
  1663.     STDMETHOD(GetClientSite)(IOleClientSite **ppClientSite)
  1664.     {
  1665.         T* pT = static_cast<T*>(this);
  1666.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetClientSite\n"));
  1667.         return pT->IOleObject_GetClientSite(ppClientSite);
  1668.     }
  1669.     STDMETHOD(SetHostNames)(LPCOLESTR /* szContainerApp */, LPCOLESTR /* szContainerObj */)
  1670.     {
  1671.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetHostNames\n"));
  1672.         return S_OK;
  1673.     }
  1674.     STDMETHOD(Close)(DWORD dwSaveOption)
  1675.     {
  1676.         T* pT = static_cast<T*>(this);
  1677.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Close\n"));
  1678.         return pT->IOleObject_Close(dwSaveOption);
  1679.     }
  1680.     STDMETHOD(SetMoniker)(DWORD /* dwWhichMoniker */, IMoniker* /* pmk */)
  1681.     {
  1682.         ATLTRACENOTIMPL(_T("IOleObjectImpl::SetMoniker"));
  1683.     }
  1684.     STDMETHOD(GetMoniker)(DWORD /* dwAssign */, DWORD /* dwWhichMoniker */, IMoniker** /* ppmk */)
  1685.     {
  1686.         ATLTRACENOTIMPL(_T("IOleObjectImpl::GetMoniker"));
  1687.     }
  1688.     STDMETHOD(InitFromData)(IDataObject* /* pDataObject */, BOOL /* fCreation */, DWORD /* dwReserved */)
  1689.     {
  1690.         ATLTRACENOTIMPL(_T("IOleObjectImpl::InitFromData"));
  1691.     }
  1692.     STDMETHOD(GetClipboardData)(DWORD /* dwReserved */, IDataObject** /* ppDataObject */)
  1693.     {
  1694.         ATLTRACENOTIMPL(_T("IOleObjectImpl::GetClipboardData"));
  1695.     }
  1696.  
  1697.     // Helpers for DoVerb - Over-rideable in user class
  1698.     HRESULT DoVerbPrimary(LPCRECT prcPosRect, HWND hwndParent)
  1699.     {
  1700.         T* pT = static_cast<T*>(this);
  1701.         BOOL bDesignMode = FALSE;
  1702.         CComVariant var;
  1703.         // if container doesn't support this property
  1704.         // don't allow design mode
  1705.         HRESULT hRes = pT->GetAmbientProperty(DISPID_AMBIENT_USERMODE, var);
  1706.         if (SUCCEEDED(hRes) && var.vt == VT_BOOL && !var.boolVal)
  1707.             bDesignMode = TRUE;
  1708.         if (bDesignMode)
  1709.             return pT->DoVerbProperties(prcPosRect, hwndParent);
  1710.         else
  1711.             return pT->DoVerbInPlaceActivate(prcPosRect, hwndParent);
  1712.     }
  1713.     HRESULT DoVerbShow(LPCRECT prcPosRect, HWND /* hwndParent */)
  1714.     {
  1715.         T* pT = static_cast<T*>(this);
  1716.         HRESULT hr;
  1717.         hr = pT->OnPreVerbShow();
  1718.         if (SUCCEEDED(hr))
  1719.         {
  1720.             hr = pT->InPlaceActivate(OLEIVERB_SHOW, prcPosRect);
  1721.             if (SUCCEEDED(hr))
  1722.                 hr = pT->OnPostVerbShow();
  1723.         }
  1724.         return hr;
  1725.     }
  1726.     HRESULT DoVerbInPlaceActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
  1727.     {
  1728.         T* pT = static_cast<T*>(this);
  1729.         HRESULT hr;
  1730.         hr = pT->OnPreVerbInPlaceActivate();
  1731.         if (SUCCEEDED(hr))
  1732.         {
  1733.             hr = pT->InPlaceActivate(OLEIVERB_INPLACEACTIVATE, prcPosRect);
  1734.             if (SUCCEEDED(hr))
  1735.                 hr = pT->OnPostVerbInPlaceActivate();
  1736.             if (SUCCEEDED(hr))
  1737.                 pT->FireViewChange();
  1738.         }
  1739.         return hr;
  1740.     }
  1741.     HRESULT DoVerbUIActivate(LPCRECT prcPosRect, HWND /* hwndParent */)
  1742.     {
  1743.         T* pT = static_cast<T*>(this);
  1744.         HRESULT hr = S_OK;
  1745.         if (!pT->m_bUIActive)
  1746.         {
  1747.             hr = pT->OnPreVerbUIActivate();
  1748.             if (SUCCEEDED(hr))
  1749.             {
  1750.                 hr = pT->InPlaceActivate(OLEIVERB_UIACTIVATE, prcPosRect);
  1751.                 if (SUCCEEDED(hr))
  1752.                     hr = pT->OnPostVerbUIActivate();
  1753.             }
  1754.         }
  1755.         return hr;
  1756.     }
  1757.     HRESULT DoVerbHide(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
  1758.     {
  1759.         T* pT = static_cast<T*>(this);
  1760.         HRESULT hr;
  1761.         hr = pT->OnPreVerbHide();
  1762.         if (SUCCEEDED(hr))
  1763.         {
  1764.             pT->UIDeactivate();
  1765.             if (pT->m_hWnd)
  1766.                 pT->ShowWindow(SW_HIDE);
  1767.             hr = pT->OnPostVerbHide();
  1768.         }
  1769.         return hr;
  1770.     }
  1771.     HRESULT DoVerbOpen(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
  1772.     {
  1773.         T* pT = static_cast<T*>(this);
  1774.         HRESULT hr;
  1775.         hr = pT->OnPreVerbOpen();
  1776.         if (SUCCEEDED(hr))
  1777.             hr = pT->OnPostVerbOpen();
  1778.         return hr;
  1779.     }
  1780.     HRESULT DoVerbDiscardUndo(LPCRECT /* prcPosRect */, HWND /* hwndParent */)
  1781.     {
  1782.         T* pT = static_cast<T*>(this);
  1783.         HRESULT hr;
  1784.         hr = pT->OnPreVerbDiscardUndo();
  1785.         if (SUCCEEDED(hr))
  1786.             hr = pT->OnPostVerbDiscardUndo();
  1787.         return hr;
  1788.     }
  1789.     STDMETHOD(DoVerb)(LONG iVerb, LPMSG /* pMsg */, IOleClientSite* /* pActiveSite */, LONG /* lindex */,
  1790.                                      HWND hwndParent, LPCRECT lprcPosRect)
  1791.     {
  1792.         T* pT = static_cast<T*>(this);
  1793.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::DoVerb(%d)\n"), iVerb);
  1794.         ATLASSERT(pT->m_spClientSite);
  1795.  
  1796.         HRESULT hr = E_NOTIMPL;
  1797.         switch (iVerb)
  1798.         {
  1799.         case OLEIVERB_PRIMARY:
  1800.             hr = pT->DoVerbPrimary(lprcPosRect, hwndParent);
  1801.             break;
  1802.         case OLEIVERB_SHOW:
  1803.             hr = pT->DoVerbShow(lprcPosRect, hwndParent);
  1804.             break;
  1805.         case OLEIVERB_INPLACEACTIVATE:
  1806.             hr = pT->DoVerbInPlaceActivate(lprcPosRect, hwndParent);
  1807.             break;
  1808.         case OLEIVERB_UIACTIVATE:
  1809.             hr = pT->DoVerbUIActivate(lprcPosRect, hwndParent);
  1810.             break;
  1811.         case OLEIVERB_HIDE:
  1812.             hr = pT->DoVerbHide(lprcPosRect, hwndParent);
  1813.             break;
  1814.         case OLEIVERB_OPEN:
  1815.             hr = pT->DoVerbOpen(lprcPosRect, hwndParent);
  1816.             break;
  1817.         case OLEIVERB_DISCARDUNDOSTATE:
  1818.             hr = pT->DoVerbDiscardUndo(lprcPosRect, hwndParent);
  1819.             break;
  1820.         case OLEIVERB_PROPERTIES:
  1821.             hr = pT->DoVerbProperties(lprcPosRect, hwndParent);
  1822.         }
  1823.         return hr;
  1824.     }
  1825.     STDMETHOD(EnumVerbs)(IEnumOLEVERB **ppEnumOleVerb)
  1826.     {
  1827.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::EnumVerbs\n"));
  1828.         ATLASSERT(ppEnumOleVerb);
  1829.         if (!ppEnumOleVerb)
  1830.             return E_POINTER;
  1831.         return OleRegEnumVerbs(T::GetObjectCLSID(), ppEnumOleVerb);
  1832.     }
  1833.     STDMETHOD(Update)(void)
  1834.     {
  1835.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Update\n"));
  1836.         return S_OK;
  1837.     }
  1838.     STDMETHOD(IsUpToDate)(void)
  1839.     {
  1840.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::IsUpToDate\n"));
  1841.         return S_OK;
  1842.     }
  1843.     STDMETHOD(GetUserClassID)(CLSID *pClsid)
  1844.     {
  1845.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetUserClassID\n"));
  1846.         ATLASSERT(pClsid);
  1847.         if (!pClsid)
  1848.             return E_POINTER;
  1849.         *pClsid = T::GetObjectCLSID();
  1850.         return S_OK;
  1851.     }
  1852.     STDMETHOD(GetUserType)(DWORD dwFormOfType, LPOLESTR *pszUserType)
  1853.     {
  1854.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetUserType\n"));
  1855.         return OleRegGetUserType(T::GetObjectCLSID(), dwFormOfType, pszUserType);
  1856.     }
  1857.     STDMETHOD(SetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
  1858.     {
  1859.         T* pT = static_cast<T*>(this);
  1860.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::SetExtent\n"));
  1861.         return pT->IOleObject_SetExtent(dwDrawAspect, psizel);
  1862.     }
  1863.     STDMETHOD(GetExtent)(DWORD dwDrawAspect, SIZEL *psizel)
  1864.     {
  1865.         T* pT = static_cast<T*>(this);
  1866.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetExtent\n"));
  1867.         if (dwDrawAspect != DVASPECT_CONTENT)
  1868.             return E_FAIL;
  1869.         if (psizel == NULL)
  1870.             return E_POINTER;
  1871.         *psizel = pT->m_sizeExtent;
  1872.         return S_OK;
  1873.     }
  1874.     STDMETHOD(Advise)(IAdviseSink *pAdvSink, DWORD *pdwConnection)
  1875.     {
  1876.         T* pT = static_cast<T*>(this);
  1877.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Advise\n"));
  1878.         return pT->IOleObject_Advise(pAdvSink, pdwConnection);
  1879.     }
  1880.     STDMETHOD(Unadvise)(DWORD dwConnection)
  1881.     {
  1882.         T* pT = static_cast<T*>(this);
  1883.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::Unadvise\n"));
  1884.         HRESULT hRes = E_FAIL;
  1885.         if (pT->m_spOleAdviseHolder != NULL)
  1886.             hRes = pT->m_spOleAdviseHolder->Unadvise(dwConnection);
  1887.         return hRes;
  1888.     }
  1889.     STDMETHOD(EnumAdvise)(IEnumSTATDATA **ppenumAdvise)
  1890.     {
  1891.         T* pT = static_cast<T*>(this);
  1892.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::EnumAdvise\n"));
  1893.         HRESULT hRes = E_FAIL;
  1894.         if (pT->m_spOleAdviseHolder != NULL)
  1895.             hRes = pT->m_spOleAdviseHolder->EnumAdvise(ppenumAdvise);
  1896.         return hRes;
  1897.     }
  1898.     STDMETHOD(GetMiscStatus)(DWORD dwAspect, DWORD *pdwStatus)
  1899.     {
  1900.         ATLTRACE2(atlTraceControls,2,_T("IOleObjectImpl::GetMiscStatus\n"));
  1901.         return OleRegGetMiscStatus(T::GetObjectCLSID(), dwAspect, pdwStatus);
  1902.     }
  1903.     STDMETHOD(SetColorScheme)(LOGPALETTE* /* pLogpal */)
  1904.     {
  1905.         ATLTRACENOTIMPL(_T("IOleObjectImpl::SetColorScheme"));
  1906.     }
  1907. // Implementation
  1908. public:
  1909.     HRESULT OnPreVerbShow() { return S_OK; }
  1910.     HRESULT OnPostVerbShow() { return S_OK; }
  1911.     HRESULT OnPreVerbInPlaceActivate() { return S_OK; }
  1912.     HRESULT OnPostVerbInPlaceActivate() { return S_OK; }
  1913.     HRESULT OnPreVerbUIActivate() { return S_OK; }
  1914.     HRESULT OnPostVerbUIActivate() { return S_OK; }
  1915.     HRESULT OnPreVerbHide() { return S_OK; }
  1916.     HRESULT OnPostVerbHide() { return S_OK; }
  1917.     HRESULT OnPreVerbOpen() { return S_OK; }
  1918.     HRESULT OnPostVerbOpen() { return S_OK; }
  1919.     HRESULT OnPreVerbDiscardUndo() { return S_OK; }
  1920.     HRESULT OnPostVerbDiscardUndo() { return S_OK; }
  1921. };
  1922.  
  1923. //local struct used for implementation
  1924. #pragma pack(push, 1)
  1925. struct _ATL_DLGTEMPLATEEX
  1926. {
  1927.     WORD dlgVer;
  1928.     WORD signature;
  1929.     DWORD helpID;
  1930.     DWORD exStyle;
  1931.     DWORD style;
  1932.     WORD cDlgItems;
  1933.     short x;
  1934.     short y;
  1935.     short cx;
  1936.     short cy;
  1937. };
  1938. #pragma pack(pop)
  1939.  
  1940. //////////////////////////////////////////////////////////////////////////////
  1941. // IPropertyPageImpl
  1942. template <class T>
  1943. class ATL_NO_VTABLE IPropertyPageImpl : public IPropertyPage
  1944. {
  1945.  
  1946. public:
  1947.     void SetDirty(BOOL bDirty)
  1948.     {
  1949.         T* pT = static_cast<T*>(this);
  1950.         if (pT->m_bDirty != bDirty)
  1951.         {
  1952.             pT->m_bDirty = bDirty;
  1953.             pT->m_pPageSite->OnStatusChange(bDirty ? PROPPAGESTATUS_DIRTY | PROPPAGESTATUS_VALIDATE : 0);
  1954.         }
  1955.     }
  1956.  
  1957.     IPropertyPageImpl()
  1958.     {
  1959.         T* pT = static_cast<T*>(this);
  1960.         pT->m_pPageSite = NULL;
  1961.         pT->m_size.cx = 0;
  1962.         pT->m_size.cy = 0;
  1963.         pT->m_dwTitleID = 0;
  1964.         pT->m_dwHelpFileID = 0;
  1965.         pT->m_dwDocStringID = 0;
  1966.         pT->m_dwHelpContext = 0;
  1967.         pT->m_ppUnk = NULL;
  1968.         pT->m_nObjects = 0;
  1969.         pT->m_bDirty = FALSE;
  1970.         pT->m_hWnd = NULL;
  1971.     }
  1972.  
  1973.     ~IPropertyPageImpl()
  1974.     {
  1975.         T* pT = static_cast<T*>(this);
  1976.         if (pT->m_pPageSite != NULL)
  1977.             pT->m_pPageSite->Release();
  1978.  
  1979.         for (UINT i = 0; i < m_nObjects; i++)
  1980.             pT->m_ppUnk[i]->Release();
  1981.  
  1982.         delete[] pT->m_ppUnk;
  1983.     }
  1984.  
  1985.     // IPropertyPage
  1986.     //
  1987.     STDMETHOD(SetPageSite)(IPropertyPageSite *pPageSite)
  1988.     {
  1989.         T* pT = static_cast<T*>(this);
  1990.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::SetPageSite\n"));
  1991.  
  1992.         if (!pPageSite && pT->m_pPageSite)
  1993.         {
  1994.             pT->m_pPageSite->Release();
  1995.             pT->m_pPageSite = NULL;
  1996.             return S_OK;
  1997.         }
  1998.  
  1999.         if (!pPageSite && !pT->m_pPageSite)
  2000.             return S_OK;
  2001.  
  2002.         if (pPageSite && pT->m_pPageSite)
  2003.         {
  2004.             ATLTRACE2(atlTraceControls,2,_T("Error : setting page site again with non NULL value\n"));
  2005.             return E_UNEXPECTED;
  2006.         }
  2007.  
  2008.         pT->m_pPageSite = pPageSite;
  2009.         pT->m_pPageSite->AddRef();
  2010.         return S_OK;
  2011.     }
  2012.     STDMETHOD(Activate)(HWND hWndParent, LPCRECT pRect, BOOL /* bModal */)
  2013.     {
  2014.         T* pT = static_cast<T*>(this);
  2015.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Activate\n"));
  2016.  
  2017.         if (pRect == NULL)
  2018.         {
  2019.             ATLTRACE2(atlTraceControls,2,_T("Error : Passed a NULL rect\n"));
  2020.             return E_POINTER;
  2021.         }
  2022.  
  2023.         pT->m_hWnd = pT->Create(hWndParent);
  2024.         Move(pRect);
  2025.  
  2026.         m_size.cx = pRect->right - pRect->left;
  2027.         m_size.cy = pRect->bottom - pRect->top;
  2028.  
  2029.         return S_OK;
  2030.  
  2031.     }
  2032.     STDMETHOD(Deactivate)( void)
  2033.     {
  2034.         T* pT = static_cast<T*>(this);
  2035.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Deactivate\n"));
  2036.  
  2037.         if (pT->m_hWnd)
  2038.         {
  2039.             ATLTRACE2(atlTraceControls,2,_T("Destroying Dialog\n"));
  2040.             if (::IsWindow(pT->m_hWnd))
  2041.                 pT->DestroyWindow();
  2042.             pT->m_hWnd = NULL;
  2043.         }
  2044.  
  2045.         return S_OK;
  2046.  
  2047.     }
  2048.     STDMETHOD(GetPageInfo)(PROPPAGEINFO *pPageInfo)
  2049.     {
  2050.         T* pT = static_cast<T*>(this);
  2051.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::GetPageInfo\n"));
  2052.  
  2053.         if (pPageInfo == NULL)
  2054.         {
  2055.             ATLTRACE2(atlTraceControls,2,_T("Error : PROPPAGEINFO passed == NULL\n"));
  2056.             return E_POINTER;
  2057.         }
  2058.  
  2059.         HRSRC hRsrc = FindResource(_Module.GetResourceInstance(),
  2060.                                    MAKEINTRESOURCE(T::IDD), RT_DIALOG);
  2061.         if (hRsrc == NULL)
  2062.         {
  2063.             ATLTRACE2(atlTraceControls,2,_T("Could not find resource template\n"));
  2064.             return E_UNEXPECTED;
  2065.         }
  2066.  
  2067.         HGLOBAL hGlob = LoadResource(_Module.GetResourceInstance(), hRsrc);
  2068.         DLGTEMPLATE* pDlgTempl = (DLGTEMPLATE*)LockResource(hGlob);
  2069.         if (pDlgTempl == NULL)
  2070.         {
  2071.             ATLTRACE2(atlTraceControls,2,_T("Could not load resource template\n"));
  2072.             return E_UNEXPECTED;
  2073.         }
  2074.         AtlGetDialogSize(pDlgTempl, &m_size);
  2075.  
  2076.         pPageInfo->cb = sizeof(PROPPAGEINFO);
  2077.         pPageInfo->pszTitle = LoadStringHelper(pT->m_dwTitleID);
  2078.         pPageInfo->size = m_size;
  2079.         pPageInfo->pszHelpFile = LoadStringHelper(pT->m_dwHelpFileID);
  2080.         pPageInfo->pszDocString = LoadStringHelper(pT->m_dwDocStringID);
  2081.         pPageInfo->dwHelpContext = pT->m_dwHelpContext;
  2082.  
  2083.         return S_OK;
  2084.     }
  2085.  
  2086.     STDMETHOD(SetObjects)(ULONG nObjects, IUnknown **ppUnk)
  2087.     {
  2088.         T* pT = static_cast<T*>(this);
  2089.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::SetObjects\n"));
  2090.  
  2091.         if (ppUnk == NULL)
  2092.             return E_POINTER;
  2093.  
  2094.         if (pT->m_ppUnk != NULL && pT->m_nObjects > 0)
  2095.         {
  2096.             for (UINT iObj = 0; iObj < pT->m_nObjects; iObj++)
  2097.                 pT->m_ppUnk[iObj]->Release();
  2098.  
  2099.             delete [] pT->m_ppUnk;
  2100.         }
  2101.  
  2102.         pT->m_ppUnk = NULL;
  2103.         ATLTRY(pT->m_ppUnk = new IUnknown*[nObjects]);
  2104.  
  2105.         if (pT->m_ppUnk == NULL)
  2106.             return E_OUTOFMEMORY;
  2107.  
  2108.         for (UINT i = 0; i < nObjects; i++)
  2109.         {
  2110.             ppUnk[i]->AddRef();
  2111.             pT->m_ppUnk[i] = ppUnk[i];
  2112.         }
  2113.  
  2114.         pT->m_nObjects = nObjects;
  2115.  
  2116.         return S_OK;
  2117.     }
  2118.     STDMETHOD(Show)(UINT nCmdShow)
  2119.     {
  2120.         T* pT = static_cast<T*>(this);
  2121.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Show\n"));
  2122.  
  2123.         if (pT->m_hWnd == NULL)
  2124.             return E_UNEXPECTED;
  2125.  
  2126.         ShowWindow(pT->m_hWnd, nCmdShow);
  2127.         return S_OK;
  2128.     }
  2129.     STDMETHOD(Move)(LPCRECT pRect)
  2130.     {
  2131.         T* pT = static_cast<T*>(this);
  2132.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Move\n"));
  2133.  
  2134.         if (pT->m_hWnd == NULL)
  2135.             return E_UNEXPECTED;
  2136.  
  2137.         if (pRect == NULL)
  2138.             return E_POINTER;
  2139.  
  2140.         MoveWindow(pT->m_hWnd, pRect->left, pRect->top, pRect->right - pRect->left,
  2141.                  pRect->bottom - pRect->top, TRUE);
  2142.  
  2143.         return S_OK;
  2144.  
  2145.     }
  2146.     STDMETHOD(IsPageDirty)(void)
  2147.     {
  2148.         T* pT = static_cast<T*>(this);
  2149.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::IsPageDirty\n"));
  2150.         return pT->m_bDirty ? S_OK : S_FALSE;
  2151.     }
  2152.     STDMETHOD(Apply)(void)
  2153.     {
  2154.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Apply\n"));
  2155.         return S_OK;
  2156.     }
  2157.     STDMETHOD(Help)(LPCOLESTR pszHelpDir)
  2158.     {
  2159.         T* pT = static_cast<T*>(this);
  2160.         USES_CONVERSION;
  2161.  
  2162.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::Help\n"));
  2163.         CComBSTR szFullFileName(pszHelpDir);
  2164.         LPOLESTR szFileName = LoadStringHelper(pT->m_dwHelpFileID);
  2165.         szFullFileName.Append(OLESTR("\\"));
  2166.         szFullFileName.Append(szFileName);
  2167.         CoTaskMemFree(szFileName);
  2168.         WinHelp(pT->m_hWnd, OLE2CT(szFullFileName), HELP_CONTEXTPOPUP, NULL);
  2169.         return S_OK;
  2170.     }
  2171.     STDMETHOD(TranslateAccelerator)(MSG *pMsg)
  2172.     {
  2173.         ATLTRACE2(atlTraceControls,2,_T("IPropertyPageImpl::TranslateAccelerator\n"));
  2174.         T* pT = static_cast<T*>(this);
  2175.         if ((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
  2176.             (pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
  2177.             return S_FALSE;
  2178.  
  2179.         return (IsDialogMessage(pT->m_hWnd, pMsg)) ? S_OK : S_FALSE;
  2180.     }
  2181.  
  2182.     IPropertyPageSite* m_pPageSite;
  2183.     IUnknown** m_ppUnk;
  2184.     ULONG m_nObjects;
  2185.     SIZE m_size;
  2186.     UINT m_dwTitleID;
  2187.     UINT m_dwHelpFileID;
  2188.     UINT m_dwDocStringID;
  2189.     DWORD m_dwHelpContext;
  2190.     BOOL m_bDirty;
  2191.  
  2192. //methods
  2193. public:
  2194.  
  2195.     BEGIN_MSG_MAP(IPropertyPageImpl<T>)
  2196.         MESSAGE_HANDLER(WM_STYLECHANGING, OnStyleChange)
  2197.     END_MSG_MAP()
  2198.  
  2199.     LRESULT OnStyleChange(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
  2200.     {
  2201.         if (wParam == GWL_EXSTYLE)
  2202.         {
  2203.             LPSTYLESTRUCT lpss = (LPSTYLESTRUCT) lParam;
  2204.             lpss->styleNew |= WS_EX_CONTROLPARENT;
  2205.             return 0;
  2206.         }
  2207.         return 1;
  2208.     }
  2209.  
  2210.     LPOLESTR LoadStringHelper(UINT idRes)
  2211.     {
  2212.         USES_CONVERSION;
  2213.  
  2214.         TCHAR szTemp[_MAX_PATH];
  2215.         LPOLESTR sz;
  2216.         sz = (LPOLESTR)CoTaskMemAlloc(_MAX_PATH*sizeof(OLECHAR));
  2217.         if (sz == NULL)
  2218.             return NULL;
  2219.         sz[0] = NULL;
  2220.  
  2221.         if (LoadString(_Module.GetResourceInstance(), idRes, szTemp, _MAX_PATH))
  2222.             ocscpy(sz, T2OLE(szTemp));
  2223.         else
  2224.         {
  2225.             ATLTRACE2(atlTraceControls,2,_T("Error : Failed to load string from res\n"));
  2226.         }
  2227.  
  2228.         return sz;
  2229.     }
  2230. };
  2231.  
  2232.  
  2233. //////////////////////////////////////////////////////////////////////////////
  2234. // IPropertyPage2Impl
  2235. template <class T>
  2236. class ATL_NO_VTABLE IPropertyPage2Impl : public IPropertyPageImpl<T>
  2237. {
  2238. public:
  2239.  
  2240.     STDMETHOD(EditProperty)(DISPID dispID)
  2241.     {
  2242.         ATLTRACENOTIMPL(_T("IPropertyPage2Impl::EditProperty\n"));
  2243.     }
  2244. };
  2245.  
  2246.  
  2247.  
  2248. //////////////////////////////////////////////////////////////////////////////
  2249. // IPerPropertyBrowsingImpl
  2250. template <class T>
  2251. class ATL_NO_VTABLE IPerPropertyBrowsingImpl : public IPerPropertyBrowsing
  2252. {
  2253. public:
  2254.     STDMETHOD(GetDisplayString)(DISPID dispID,BSTR *pBstr)
  2255.     {
  2256.         ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::GetDisplayString\n"));
  2257.         T* pT = static_cast<T*>(this);
  2258.         *pBstr = NULL;
  2259.         CComVariant var;
  2260.         if (FAILED(CComDispatchDriver::GetProperty(pT, dispID, &var)))
  2261.             return S_FALSE;
  2262.  
  2263.         BSTR bstrTemp = var.bstrVal;
  2264.         if (var.vt != VT_BSTR)
  2265.         {
  2266.             CComVariant varDest;
  2267.             if (FAILED(::VariantChangeType(&varDest, &var, VARIANT_NOVALUEPROP, VT_BSTR)))
  2268.                 return S_FALSE;
  2269.             bstrTemp = varDest.bstrVal;
  2270.         }
  2271.         *pBstr = SysAllocString(bstrTemp);
  2272.         if (*pBstr == NULL)
  2273.             return E_OUTOFMEMORY;
  2274.         return S_OK;
  2275.     }
  2276.  
  2277.     STDMETHOD(MapPropertyToPage)(DISPID dispID, CLSID *pClsid)
  2278.     {
  2279.         ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::MapPropertyToPage\n"));
  2280.         ATL_PROPMAP_ENTRY* pMap = T::GetPropertyMap();
  2281.         ATLASSERT(pMap != NULL);
  2282.         for (int i = 0; pMap[i].pclsidPropPage != NULL; i++)
  2283.         {
  2284.             if (pMap[i].szDesc == NULL)
  2285.                 continue;
  2286.  
  2287.             // reject data entry types
  2288.             if (pMap[i].dwSizeData != 0)
  2289.                 continue;
  2290.  
  2291.             if (pMap[i].dispid == dispID)
  2292.             {
  2293.                 ATLASSERT(pMap[i].pclsidPropPage != NULL);
  2294.                 *pClsid = *(pMap[i].pclsidPropPage);
  2295.                 return S_OK;
  2296.             }
  2297.         }
  2298.         *pClsid = CLSID_NULL;
  2299.         return E_INVALIDARG;
  2300.     }
  2301.     STDMETHOD(GetPredefinedStrings)(DISPID dispID, CALPOLESTR *pCaStringsOut,CADWORD *pCaCookiesOut)
  2302.     {
  2303.         dispID;
  2304.         ATLTRACE2(atlTraceControls,2,_T("IPerPropertyBrowsingImpl::GetPredefinedStrings\n"));
  2305.         if (pCaStringsOut == NULL || pCaCookiesOut == NULL)
  2306.             return E_POINTER;
  2307.  
  2308.         pCaStringsOut->cElems = 0;
  2309.         pCaStringsOut->pElems = NULL;
  2310.         pCaCookiesOut->cElems = 0;
  2311.         pCaCookiesOut->pElems = NULL;
  2312.         return S_OK;
  2313.     }
  2314.     STDMETHOD(GetPredefinedValue)(DISPID /*dispID*/, DWORD /*dwCookie*/, VARIANT* /*pVarOut*/)
  2315.     {
  2316.         ATLTRACENOTIMPL(_T("IPerPropertyBrowsingImpl::GetPredefinedValue"));
  2317.     }
  2318. };
  2319.  
  2320. //////////////////////////////////////////////////////////////////////////////
  2321. // IViewObjectExImpl
  2322. template <class T>
  2323. class ATL_NO_VTABLE IViewObjectExImpl : public IViewObjectEx
  2324. {
  2325. public:
  2326.     STDMETHOD(Draw)(DWORD dwDrawAspect, LONG lindex, void *pvAspect,
  2327.                     DVTARGETDEVICE *ptd, HDC hicTargetDev, HDC hdcDraw,
  2328.                     LPCRECTL prcBounds, LPCRECTL prcWBounds,
  2329.                     BOOL (__stdcall * /*pfnContinue*/)(DWORD dwContinue),
  2330.                     DWORD /*dwContinue*/)
  2331.     {
  2332.         T* pT = static_cast<T*>(this);
  2333.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::Draw\n"));
  2334.         return pT->IViewObject_Draw(dwDrawAspect, lindex, pvAspect, ptd, hicTargetDev, hdcDraw,
  2335.             prcBounds, prcWBounds);
  2336.     }
  2337.  
  2338.     STDMETHOD(GetColorSet)(DWORD /* dwDrawAspect */,LONG /* lindex */, void* /* pvAspect */, DVTARGETDEVICE* /* ptd */, HDC /* hicTargetDev */, LOGPALETTE** /* ppColorSet */)
  2339.     {
  2340.         ATLTRACENOTIMPL(_T("IViewObjectExImpl::GetColorSet"));
  2341.     }
  2342.     STDMETHOD(Freeze)(DWORD /* dwDrawAspect */, LONG /* lindex */, void* /* pvAspect */,DWORD* /* pdwFreeze */)
  2343.     {
  2344.         ATLTRACENOTIMPL(_T("IViewObjectExImpl::Freeze"));
  2345.     }
  2346.     STDMETHOD(Unfreeze)(DWORD /* dwFreeze */)
  2347.     {
  2348.         ATLTRACENOTIMPL(_T("IViewObjectExImpl::Unfreeze"));
  2349.     }
  2350.     STDMETHOD(SetAdvise)(DWORD /* aspects */, DWORD /* advf */, IAdviseSink* pAdvSink)
  2351.     {
  2352.         T* pT = static_cast<T*>(this);
  2353.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::SetAdvise\n"));
  2354.         pT->m_spAdviseSink = pAdvSink;
  2355.         return S_OK;
  2356.     }
  2357.     STDMETHOD(GetAdvise)(DWORD* /* pAspects */, DWORD* /* pAdvf */, IAdviseSink** ppAdvSink)
  2358.     {
  2359.         T* pT = static_cast<T*>(this);
  2360.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetAdvise\n"));
  2361.         if (ppAdvSink != NULL)
  2362.         {
  2363.             *ppAdvSink = pT->m_spAdviseSink;
  2364.             if (pT->m_spAdviseSink)
  2365.                 pT->m_spAdviseSink.p->AddRef();
  2366.         }
  2367.         return S_OK;
  2368.     }
  2369.  
  2370.     // IViewObject2
  2371.     //
  2372.     STDMETHOD(GetExtent)(DWORD /* dwDrawAspect */, LONG /* lindex */, DVTARGETDEVICE* /* ptd */, LPSIZEL lpsizel)
  2373.     {
  2374.         T* pT = static_cast<T*>(this);
  2375.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetExtent\n"));
  2376.         *lpsizel = pT->m_sizeExtent;
  2377.         return S_OK;
  2378.     }
  2379.  
  2380.     // IViewObjectEx
  2381.     //
  2382.     STDMETHOD(GetRect)(DWORD /* dwAspect */, LPRECTL /* pRect */)
  2383.     {
  2384.         ATLTRACENOTIMPL(_T("IViewObjectExImpl::GetRect"));
  2385.     }
  2386.  
  2387.     STDMETHOD(GetViewStatus)(DWORD* pdwStatus)
  2388.     {
  2389.         T* pT = static_cast<T*>(this);
  2390.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetViewStatus\n"));
  2391.         *pdwStatus = pT->_GetViewStatus();
  2392.         return S_OK;
  2393.     }
  2394.     STDMETHOD(QueryHitPoint)(DWORD dwAspect, LPCRECT pRectBounds, POINT ptlLoc, LONG /* lCloseHint */, DWORD *pHitResult)
  2395.     {
  2396.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::QueryHitPoint\n"));
  2397.         if (dwAspect == DVASPECT_CONTENT)
  2398.         {
  2399.             *pHitResult = PtInRect(pRectBounds, ptlLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  2400.             return S_OK;
  2401.         }
  2402.         ATLTRACE2(atlTraceControls,2,_T("Wrong DVASPECT\n"));
  2403.         return E_FAIL;
  2404.     }
  2405.     STDMETHOD(QueryHitRect)(DWORD dwAspect, LPCRECT pRectBounds, LPCRECT prcLoc, LONG /* lCloseHint */, DWORD* pHitResult)
  2406.     {
  2407.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::QueryHitRect\n"));
  2408.         if (dwAspect == DVASPECT_CONTENT)
  2409.         {
  2410.             RECT rc;
  2411.             *pHitResult = UnionRect(&rc, pRectBounds, prcLoc) ? HITRESULT_HIT : HITRESULT_OUTSIDE;
  2412.             return S_OK;
  2413.         }
  2414.         ATLTRACE2(atlTraceControls,2,_T("Wrong DVASPECT\n"));
  2415.         return E_FAIL;
  2416.     }
  2417.     STDMETHOD(GetNaturalExtent)(DWORD dwAspect, LONG /* lindex */, DVTARGETDEVICE* /* ptd */, HDC /* hicTargetDev */, DVEXTENTINFO* pExtentInfo , LPSIZEL psizel)
  2418.     {
  2419.         T* pT = static_cast<T*>(this);
  2420.         ATLTRACE2(atlTraceControls,2,_T("IViewObjectExImpl::GetNaturalExtent\n"));
  2421.         HRESULT hRes = E_FAIL;
  2422.         if (pExtentInfo == NULL || psizel == NULL)
  2423.             hRes = E_POINTER;
  2424.         else if (dwAspect == DVASPECT_CONTENT)
  2425.         {
  2426.             if (pExtentInfo->dwExtentMode == DVEXTENT_CONTENT)
  2427.             {
  2428.                 *psizel = pT->m_sizeNatural;
  2429.                 hRes = S_OK;
  2430.             }
  2431.         }
  2432.         return hRes;
  2433.     }
  2434.  
  2435. public:
  2436. };
  2437.  
  2438. //////////////////////////////////////////////////////////////////////////////
  2439. // IOleInPlaceObjectWindowlessImpl
  2440. //
  2441. template <class T>
  2442. class ATL_NO_VTABLE IOleInPlaceObjectWindowlessImpl : public IOleInPlaceObjectWindowless
  2443. {
  2444. public:
  2445.     // IOleWindow
  2446.     //
  2447.  
  2448.     // Change IOleInPlaceActiveObject::GetWindow as well
  2449.     STDMETHOD(GetWindow)(HWND* phwnd)
  2450.     {
  2451.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::GetWindow\n"));
  2452.         T* pT = static_cast<T*>(this);
  2453.         HRESULT hRes = E_POINTER;
  2454.  
  2455.         if (pT->m_bWasOnceWindowless)
  2456.             return E_FAIL;
  2457.  
  2458.         if (phwnd != NULL)
  2459.         {
  2460.             *phwnd = pT->m_hWnd;
  2461.             hRes = (*phwnd == NULL) ? E_UNEXPECTED : S_OK;
  2462.         }
  2463.         return hRes;
  2464.     }
  2465.     STDMETHOD(ContextSensitiveHelp)(BOOL /* fEnterMode */)
  2466.     {
  2467.         ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::ContextSensitiveHelp"));
  2468.     }
  2469.  
  2470.     // IOleInPlaceObject
  2471.     //
  2472.     STDMETHOD(InPlaceDeactivate)(void)
  2473.     {
  2474.         T* pT = static_cast<T*>(this);
  2475.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::InPlaceDeactivate\n"));
  2476.         return pT->IOleInPlaceObject_InPlaceDeactivate();
  2477.     }
  2478.     STDMETHOD(UIDeactivate)(void)
  2479.     {
  2480.         T* pT = static_cast<T*>(this);
  2481.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::UIDeactivate\n"));
  2482.         return pT->IOleInPlaceObject_UIDeactivate();
  2483.     }
  2484.     STDMETHOD(SetObjectRects)(LPCRECT prcPos,LPCRECT prcClip)
  2485.     {
  2486.         T* pT = static_cast<T*>(this);
  2487.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::SetObjectRects\n"));
  2488.         return pT->IOleInPlaceObject_SetObjectRects(prcPos, prcClip);
  2489.     }
  2490.     STDMETHOD(ReactivateAndUndo)(void)
  2491.     {
  2492.         ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::ReactivateAndUndo"));
  2493.     }
  2494.  
  2495.     // IOleInPlaceObjectWindowless
  2496.     //
  2497.     STDMETHOD(OnWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT *plResult)
  2498.     {
  2499.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceObjectWindowlessImpl::OnWindowMessage\n"));
  2500.         T* pT = static_cast<T*>(this);
  2501.         BOOL b = pT->ProcessWindowMessage(pT->m_hWnd, msg, wParam, lParam, *plResult);
  2502.         return b ? S_OK : S_FALSE;
  2503.     }
  2504.  
  2505.     STDMETHOD(GetDropTarget)(IDropTarget** /* ppDropTarget */)
  2506.     {
  2507.         ATLTRACENOTIMPL(_T("IOleInPlaceObjectWindowlessImpl::GetDropTarget"));
  2508.     }
  2509. };
  2510.  
  2511.  
  2512. //////////////////////////////////////////////////////////////////////////////
  2513. // IOleInPlaceActiveObjectImpl
  2514. //
  2515. template <class T>
  2516. class ATL_NO_VTABLE IOleInPlaceActiveObjectImpl : public IOleInPlaceActiveObject
  2517. {
  2518. public:
  2519.     // IOleWindow
  2520.     //
  2521.  
  2522.     // Change IOleInPlaceObjectWindowless::GetWindow as well
  2523.     STDMETHOD(GetWindow)(HWND *phwnd)
  2524.     {
  2525.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::GetWindow\n"));
  2526.         T* pT = static_cast<T*>(this);
  2527.         HRESULT hRes = E_POINTER;
  2528.  
  2529.         if (pT->m_bWasOnceWindowless)
  2530.             return E_FAIL;
  2531.  
  2532.         if (phwnd != NULL)
  2533.         {
  2534.             *phwnd = pT->m_hWnd;
  2535.             hRes = (*phwnd == NULL) ? E_UNEXPECTED : S_OK;
  2536.         }
  2537.         return hRes;
  2538.     }
  2539.     STDMETHOD(ContextSensitiveHelp)(BOOL /* fEnterMode */)
  2540.     {
  2541.         ATLTRACENOTIMPL(_T("IOleInPlaceActiveObjectImpl::ContextSensitiveHelp"));
  2542.     }
  2543.  
  2544.     // IOleInPlaceActiveObject
  2545.     //
  2546.     STDMETHOD(TranslateAccelerator)(LPMSG pMsg)
  2547.     {
  2548.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::TranslateAccelerator\n"));
  2549.         T* pT = static_cast<T*>(this);
  2550.         HRESULT hRet = S_OK;
  2551.         if (pT->PreTranslateAccelerator(pMsg, hRet))
  2552.             return hRet;
  2553.         CComPtr<IOleControlSite> spCtlSite;
  2554.         hRet = pT->InternalGetSite(IID_IOleControlSite, (void**)&spCtlSite);
  2555.         if (SUCCEEDED(hRet))
  2556.         {
  2557.             if (spCtlSite != NULL)
  2558.             {
  2559.                 DWORD dwKeyMod = 0;
  2560.                 if (::GetKeyState(VK_SHIFT) < 0)
  2561.                     dwKeyMod += 1;    // KEYMOD_SHIFT
  2562.                 if (::GetKeyState(VK_CONTROL) < 0)
  2563.                     dwKeyMod += 2;    // KEYMOD_CONTROL
  2564.                 if (::GetKeyState(VK_MENU) < 0)
  2565.                     dwKeyMod += 4;    // KEYMOD_ALT
  2566.                 hRet = spCtlSite->TranslateAccelerator(pMsg, dwKeyMod);
  2567.             }
  2568.             else
  2569.                 hRet = S_FALSE;
  2570.         }
  2571.         return (hRet == S_OK) ? S_OK : S_FALSE;
  2572.     }
  2573.     STDMETHOD(OnFrameWindowActivate)(BOOL /* fActivate */)
  2574.     {
  2575.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::OnFrameWindowActivate\n"));
  2576.         return S_OK;
  2577.     }
  2578.     STDMETHOD(OnDocWindowActivate)(BOOL fActivate)
  2579.     {
  2580.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::OnDocWindowActivate\n"));
  2581.         T* pT = static_cast<T*>(this);
  2582.         if (fActivate == FALSE)
  2583.             pT->IOleInPlaceObject_UIDeactivate();
  2584.         return S_OK;
  2585.     }
  2586.     STDMETHOD(ResizeBorder)(LPCRECT /* prcBorder */, IOleInPlaceUIWindow* /* pUIWindow */, BOOL /* fFrameWindow */)
  2587.     {
  2588.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::ResizeBorder\n"));
  2589.         return S_OK;
  2590.     }
  2591.     STDMETHOD(EnableModeless)(BOOL /* fEnable */)
  2592.     {
  2593.         ATLTRACE2(atlTraceControls,2,_T("IOleInPlaceActiveObjectImpl::EnableModeless\n"));
  2594.         return S_OK;
  2595.     }
  2596. };
  2597.  
  2598. //////////////////////////////////////////////////////////////////////////////
  2599. // IPointerInactiveImpl
  2600. template <class T>
  2601. class ATL_NO_VTABLE IPointerInactiveImpl : public IPointerInactive
  2602. {
  2603. public:
  2604.     // IPointerInactive
  2605.     //
  2606.     STDMETHOD(GetActivationPolicy)(DWORD *pdwPolicy)
  2607.     {
  2608.         ATLTRACENOTIMPL(_T("IPointerInactiveImpl::GetActivationPolicy"));
  2609.     }
  2610.     STDMETHOD(OnInactiveMouseMove)(LPCRECT pRectBounds, long x, long y, DWORD dwMouseMsg)
  2611.     {
  2612.         ATLTRACENOTIMPL(_T("IPointerInactiveImpl::OnInactiveMouseMove"));
  2613.     }
  2614.     STDMETHOD(OnInactiveSetCursor)(LPCRECT pRectBounds, long x, long y, DWORD dwMouseMsg, BOOL fSetAlways)
  2615.     {
  2616.         ATLTRACENOTIMPL(_T("IPointerInactiveImpl::OnInactiveSetCursor"));
  2617.     }
  2618. };
  2619.  
  2620. //////////////////////////////////////////////////////////////////////////////
  2621. // IRunnableObjectImpl
  2622. template <class T>
  2623. class ATL_NO_VTABLE IRunnableObjectImpl : public IRunnableObject
  2624. {
  2625. public:
  2626.     // IRunnableObject
  2627.     //
  2628.     STDMETHOD(GetRunningClass)(LPCLSID lpClsid)
  2629.     {
  2630.         ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::GetRunningClass\n"));
  2631.         *lpClsid = GUID_NULL;
  2632.         return E_UNEXPECTED;
  2633.     }
  2634.     STDMETHOD(Run)(LPBINDCTX)
  2635.     {
  2636.         ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::Run\n"));
  2637.         return S_OK;
  2638.     }
  2639.     virtual BOOL STDMETHODCALLTYPE IsRunning()
  2640.     {
  2641.         ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::IsRunning\n"));
  2642.         return TRUE;
  2643.     }
  2644.     STDMETHOD(LockRunning)(BOOL /*fLock*/, BOOL /*fLastUnlockCloses*/)
  2645.     {
  2646.         ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::LockRunning\n"));
  2647.         return S_OK;
  2648.     }
  2649.     STDMETHOD(SetContainedObject)(BOOL /*fContained*/)
  2650.     {
  2651.         ATLTRACE2(atlTraceControls,2,_T("IRunnableObjectImpl::SetContainedObject\n"));
  2652.         return S_OK;
  2653.     }
  2654. };
  2655.  
  2656.  
  2657. //////////////////////////////////////////////////////////////////////////////
  2658. // IDataObjectImpl
  2659. template <class T>
  2660. class ATL_NO_VTABLE IDataObjectImpl : public IDataObject
  2661. {
  2662. public:
  2663.     STDMETHOD(GetData)(FORMATETC *pformatetcIn, STGMEDIUM *pmedium)
  2664.     {
  2665.         ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::GetData\n"));
  2666.         T* pT = (T*) this;
  2667.         return pT->IDataObject_GetData(pformatetcIn, pmedium);
  2668.     }
  2669.     STDMETHOD(GetDataHere)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */)
  2670.     {
  2671.         ATLTRACENOTIMPL(_T("IDataObjectImpl::GetDataHere"));
  2672.     }
  2673.     STDMETHOD(QueryGetData)(FORMATETC* /* pformatetc */)
  2674.     {
  2675.         ATLTRACENOTIMPL(_T("IDataObjectImpl::QueryGetData"));
  2676.     }
  2677.     STDMETHOD(GetCanonicalFormatEtc)(FORMATETC* /* pformatectIn */,FORMATETC* /* pformatetcOut */)
  2678.     {
  2679.         ATLTRACENOTIMPL(_T("IDataObjectImpl::GetCanonicalFormatEtc"));
  2680.     }
  2681.     STDMETHOD(SetData)(FORMATETC* /* pformatetc */, STGMEDIUM* /* pmedium */, BOOL /* fRelease */)
  2682.     {
  2683.         ATLTRACENOTIMPL(_T("IDataObjectImpl::SetData"));
  2684.     }
  2685.     STDMETHOD(EnumFormatEtc)(DWORD /* dwDirection */, IEnumFORMATETC** /* ppenumFormatEtc */)
  2686.     {
  2687.         ATLTRACENOTIMPL(_T("IDataObjectImpl::EnumFormatEtc"));
  2688.     }
  2689.     STDMETHOD(DAdvise)(FORMATETC *pformatetc, DWORD advf, IAdviseSink *pAdvSink,
  2690.         DWORD *pdwConnection)
  2691.     {
  2692.         ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::DAdvise\n"));
  2693.         T* pT = static_cast<T*>(this);
  2694.         HRESULT hr = S_OK;
  2695.         if (pT->m_spDataAdviseHolder == NULL)
  2696.             hr = CreateDataAdviseHolder(&pT->m_spDataAdviseHolder);
  2697.  
  2698.         if (hr == S_OK)
  2699.             hr = pT->m_spDataAdviseHolder->Advise((IDataObject*)this, pformatetc, advf, pAdvSink, pdwConnection);
  2700.  
  2701.         return hr;
  2702.     }
  2703.     STDMETHOD(DUnadvise)(DWORD dwConnection)
  2704.     {
  2705.         ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::DUnadvise\n"));
  2706.         T* pT = static_cast<T*>(this);
  2707.         HRESULT hr = S_OK;
  2708.         if (pT->m_spDataAdviseHolder == NULL)
  2709.             hr = OLE_E_NOCONNECTION;
  2710.         else
  2711.             hr = pT->m_spDataAdviseHolder->Unadvise(dwConnection);
  2712.         return hr;
  2713.     }
  2714.     STDMETHOD(EnumDAdvise)(IEnumSTATDATA **ppenumAdvise)
  2715.     {
  2716.         ATLTRACE2(atlTraceControls,2,_T("IDataObjectImpl::EnumDAdvise\n"));
  2717.         T* pT = static_cast<T*>(this);
  2718.         HRESULT hr = E_FAIL;
  2719.         if (pT->m_spDataAdviseHolder != NULL)
  2720.             hr = pT->m_spDataAdviseHolder->EnumAdvise(ppenumAdvise);
  2721.         return hr;
  2722.     }
  2723. };
  2724.  
  2725. //////////////////////////////////////////////////////////////////////////////
  2726. // IPropertyNotifySinkCP
  2727. template <class T, class CDV = CComDynamicUnkArray >
  2728. class ATL_NO_VTABLE IPropertyNotifySinkCP :
  2729.     public IConnectionPointImpl<T, &IID_IPropertyNotifySink, CDV>
  2730. {
  2731. public:
  2732.     typedef CFirePropNotifyEvent _ATL_PROP_NOTIFY_EVENT_CLASS;
  2733. };
  2734.  
  2735.  
  2736. //////////////////////////////////////////////////////////////////////////////
  2737. // IObjectSafety
  2738. //
  2739. // 2nd template parameter is the supported safety e.g.
  2740. // INTERFACESAFE_FOR_UNTRUSTED_CALLER - safe for scripting
  2741. // INTERFACESAFE_FOR_UNTRUSTED_DATA   - safe for initialization from data
  2742.  
  2743. template <class T, DWORD dwSupportedSafety>
  2744. class ATL_NO_VTABLE IObjectSafetyImpl : public IObjectSafety
  2745. {
  2746. public:
  2747.     IObjectSafetyImpl()
  2748.     {
  2749.         m_dwCurrentSafety = 0;
  2750.     }
  2751.  
  2752.     STDMETHOD(GetInterfaceSafetyOptions)(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
  2753.     {
  2754.         ATLTRACE2(atlTraceControls,2,_T("IObjectSafetyImpl2::GetInterfaceSafetyOptions\n"));
  2755.         T* pT = static_cast<T*>(this);
  2756.         if (pdwSupportedOptions == NULL || pdwEnabledOptions == NULL)
  2757.             return E_POINTER;
  2758.         
  2759.         HRESULT hr;
  2760.         IUnknown* pUnk;
  2761.         // Check if we support this interface
  2762.         hr = pT->GetUnknown()->QueryInterface(riid, (void**)&pUnk);
  2763.         if (SUCCEEDED(hr))
  2764.         {
  2765.             // We support this interface so set the safety options accordingly
  2766.             pUnk->Release();    // Release the interface we just acquired
  2767.             *pdwSupportedOptions = dwSupportedSafety;
  2768.             *pdwEnabledOptions   = m_dwCurrentSafety;
  2769.         }
  2770.         else
  2771.         {
  2772.             // We don't support this interface
  2773.             *pdwSupportedOptions = 0;
  2774.             *pdwEnabledOptions   = 0;
  2775.         }
  2776.         return hr;
  2777.     }
  2778.     STDMETHOD(SetInterfaceSafetyOptions)(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
  2779.     {
  2780.         ATLTRACE2(atlTraceControls,2,_T("IObjectSafetyImpl2::SetInterfaceSafetyOptions\n"));
  2781.         T* pT = static_cast<T*>(this);
  2782.         IUnknown* pUnk;
  2783.         
  2784.         // Check if we support the interface and return E_NOINTEFACE if we don't
  2785.         if (FAILED(pT->GetUnknown()->QueryInterface(riid, (void**)&pUnk)))
  2786.             return E_NOINTERFACE;
  2787.         pUnk->Release();    // Release the interface we just acquired
  2788.         
  2789.         // If we are asked to set options we don't support then fail
  2790.         if (dwOptionSetMask & ~dwSupportedSafety)
  2791.             return E_FAIL;
  2792.  
  2793.         // Set the safety options we have been asked to
  2794.         m_dwCurrentSafety = m_dwCurrentSafety  & ~dwEnabledOptions | dwOptionSetMask;
  2795.         return S_OK;
  2796.     }
  2797.     DWORD m_dwCurrentSafety;
  2798. };
  2799.  
  2800. template <class T>
  2801. class ATL_NO_VTABLE IOleLinkImpl : public IOleLink
  2802. {
  2803.     STDMETHOD(SetUpdateOptions)(DWORD /* dwUpdateOpt */)
  2804.     {
  2805.         ATLTRACENOTIMPL(_T("IOleLinkImpl::SetUpdateOptions"));
  2806.     }
  2807.  
  2808.     STDMETHOD(GetUpdateOptions)(DWORD* /* pdwUpdateOpt */)
  2809.     {
  2810.         ATLTRACENOTIMPL(_T("IOleLinkImpl::GetUpdateOptions"));
  2811.     }
  2812.  
  2813.     STDMETHOD(SetSourceMoniker)(IMoniker* /* pmk */, REFCLSID /* rclsid */)
  2814.     {
  2815.         ATLTRACENOTIMPL(_T("IOleLinkImpl::SetSourceMoniker"));
  2816.     }
  2817.  
  2818.     STDMETHOD(GetSourceMoniker)(IMoniker** /* ppmk */)
  2819.     {
  2820.         ATLTRACENOTIMPL(_T("IOleLinkImpl::GetSourceMoniker"));
  2821.     };
  2822.  
  2823.     STDMETHOD(SetSourceDisplayName)(LPCOLESTR /* pszStatusText */)
  2824.     {
  2825.         ATLTRACENOTIMPL(_T("IOleLinkImpl::SetSourceDisplayName"));
  2826.     }
  2827.  
  2828.     STDMETHOD(GetSourceDisplayName)(LPOLESTR *ppszDisplayName)
  2829.     {
  2830.         ATLTRACE2(atlTraceControls,2,_T("IOleLink::GetSourceDisplayName\n"));
  2831.         *ppszDisplayName = NULL;
  2832.         return E_FAIL;
  2833.     }
  2834.  
  2835.     STDMETHOD(BindToSource)(DWORD /* bindflags */, IBindCtx* /* pbc */)
  2836.     {
  2837.         ATLTRACENOTIMPL(_T("IOleLinkImpl::BindToSource\n"));
  2838.     };
  2839.  
  2840.     STDMETHOD(BindIfRunning)()
  2841.     {
  2842.         ATLTRACE2(atlTraceControls,2,_T("IOleLinkImpl::BindIfRunning\n"));
  2843.         return S_OK;
  2844.     };
  2845.  
  2846.     STDMETHOD(GetBoundSource)(IUnknown** /* ppunk */)
  2847.     {
  2848.         ATLTRACENOTIMPL(_T("IOleLinkImpl::GetBoundSource"));
  2849.     };
  2850.  
  2851.     STDMETHOD(UnbindSource)()
  2852.     {
  2853.         ATLTRACENOTIMPL(_T("IOleLinkImpl::UnbindSource"));
  2854.     };
  2855.  
  2856.     STDMETHOD(Update)(IBindCtx* /* pbc */)
  2857.     {
  2858.         ATLTRACENOTIMPL(_T("IOleLinkImpl::Update"));
  2859.     };
  2860. };
  2861.  
  2862. template <class T>
  2863. class ATL_NO_VTABLE CBindStatusCallback :
  2864.     public CComObjectRootEx<T::_ThreadModel::ThreadModelNoCS>,
  2865.     public IBindStatusCallback
  2866. {
  2867.     typedef void (T::*ATL_PDATAAVAILABLE)(CBindStatusCallback<T>* pbsc, BYTE* pBytes, DWORD dwSize);
  2868.  
  2869. public:
  2870.  
  2871. BEGIN_COM_MAP(CBindStatusCallback<T>)
  2872.     COM_INTERFACE_ENTRY(IBindStatusCallback)
  2873. END_COM_MAP()
  2874.  
  2875.     CBindStatusCallback()
  2876.     {
  2877.         m_pT = NULL;
  2878.         m_pFunc = NULL;
  2879.     }
  2880.     ~CBindStatusCallback()
  2881.     {
  2882.         ATLTRACE2(atlTraceControls,2,_T("~CBindStatusCallback\n"));
  2883.     }
  2884.  
  2885.     STDMETHOD(OnStartBinding)(DWORD dwReserved, IBinding *pBinding)
  2886.     {
  2887.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnStartBinding\n"));
  2888.         m_spBinding = pBinding;
  2889.         return S_OK;
  2890.     }
  2891.  
  2892.     STDMETHOD(GetPriority)(LONG *pnPriority)
  2893.     {
  2894.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::GetPriority"));
  2895.         HRESULT hr = S_OK;
  2896.         if (pnPriority)
  2897.             *pnPriority = THREAD_PRIORITY_NORMAL;
  2898.         else
  2899.             hr = E_INVALIDARG;
  2900.         return S_OK;
  2901.     }
  2902.  
  2903.     STDMETHOD(OnLowResource)(DWORD reserved)
  2904.     {
  2905.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnLowResource"));
  2906.         return S_OK;
  2907.     }
  2908.  
  2909.     STDMETHOD(OnProgress)(ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
  2910.     {
  2911.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnProgress"));
  2912.         return S_OK;
  2913.     }
  2914.  
  2915.     STDMETHOD(OnStopBinding)(HRESULT hresult, LPCWSTR szError)
  2916.     {
  2917.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnStopBinding\n"));
  2918.         (m_pT->*m_pFunc)(this, NULL, 0);
  2919.         m_spBinding.Release();
  2920.         m_spBindCtx.Release();
  2921.         m_spMoniker.Release();
  2922.         return S_OK;
  2923.     }
  2924.  
  2925.     STDMETHOD(GetBindInfo)(DWORD *pgrfBINDF, BINDINFO *pbindInfo)
  2926.     {
  2927.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::GetBindInfo\n"));
  2928.  
  2929.         if (pbindInfo==NULL || pbindInfo->cbSize==0 || pgrfBINDF==NULL)
  2930.             return E_INVALIDARG;
  2931.  
  2932.         *pgrfBINDF = BINDF_ASYNCHRONOUS | BINDF_ASYNCSTORAGE |
  2933.             BINDF_GETNEWESTVERSION | BINDF_NOWRITECACHE;
  2934.  
  2935.         ULONG cbSize = pbindInfo->cbSize;        // remember incoming cbSize
  2936.         memset(pbindInfo, 0, cbSize);            // zero out structure
  2937.         pbindInfo->cbSize = cbSize;                // restore cbSize
  2938.         pbindInfo->dwBindVerb = BINDVERB_GET;    // set verb
  2939.         return S_OK;
  2940.     }
  2941.  
  2942.     STDMETHOD(OnDataAvailable)(DWORD grfBSCF, DWORD dwSize, FORMATETC *pformatetc, STGMEDIUM *pstgmed)
  2943.     {
  2944.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnDataAvailable\n"));
  2945.         HRESULT hr = S_OK;
  2946.  
  2947.         // Get the Stream passed
  2948.         if (BSCF_FIRSTDATANOTIFICATION & grfBSCF)
  2949.         {
  2950.             if (!m_spStream && pstgmed->tymed == TYMED_ISTREAM)
  2951.                 m_spStream = pstgmed->pstm;
  2952.         }
  2953.  
  2954.         DWORD dwRead = dwSize - m_dwTotalRead; // Minimum amount available that hasn't been read
  2955.         DWORD dwActuallyRead = 0;            // Placeholder for amount read during this pull
  2956.  
  2957.         // If there is some data to be read then go ahead and read them
  2958.         if (m_spStream)
  2959.         {
  2960.             if (dwRead > 0)
  2961.             {
  2962.                 BYTE* pBytes = NULL;
  2963.                 ATLTRY(pBytes = new BYTE[dwRead + 1]);
  2964.                 if (pBytes == NULL)
  2965.                     return E_OUTOFMEMORY;
  2966.                 hr = m_spStream->Read(pBytes, dwRead, &dwActuallyRead);
  2967.                 if (SUCCEEDED(hr))
  2968.                 {
  2969.                     pBytes[dwActuallyRead] = 0;
  2970.                     if (dwActuallyRead>0)
  2971.                     {
  2972.                         (m_pT->*m_pFunc)(this, pBytes, dwActuallyRead);
  2973.                         m_dwTotalRead += dwActuallyRead;
  2974.                     }
  2975.                 }
  2976.                 delete[] pBytes;
  2977.             }
  2978.         }
  2979.  
  2980.         if (BSCF_LASTDATANOTIFICATION & grfBSCF)
  2981.             m_spStream.Release();
  2982.         return hr;
  2983.     }
  2984.  
  2985.     STDMETHOD(OnObjectAvailable)(REFIID riid, IUnknown *punk)
  2986.     {
  2987.         ATLTRACE2(atlTraceControls,2,_T("CBindStatusCallback::OnObjectAvailable"));
  2988.         return S_OK;
  2989.     }
  2990.  
  2991.     HRESULT _StartAsyncDownload(BSTR bstrURL, IUnknown* pUnkContainer, BOOL bRelative)
  2992.     {
  2993.         m_dwTotalRead = 0;
  2994.         m_dwAvailableToRead = 0;
  2995.         HRESULT hr = S_OK;
  2996.         CComQIPtr<IServiceProvider, &IID_IServiceProvider> spServiceProvider(pUnkContainer);
  2997.         CComPtr<IBindHost>    spBindHost;
  2998.         CComPtr<IStream>    spStream;
  2999.         if (spServiceProvider)
  3000.             spServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&spBindHost);
  3001.  
  3002.         if (spBindHost == NULL)
  3003.         {
  3004.             if (bRelative)
  3005.                 return E_NOINTERFACE;  // relative asked for, but no IBindHost
  3006.             hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
  3007.             if (SUCCEEDED(hr))
  3008.                 hr = CreateBindCtx(0, &m_spBindCtx);
  3009.  
  3010.             if (SUCCEEDED(hr))
  3011.                 hr = RegisterBindStatusCallback(m_spBindCtx, static_cast<IBindStatusCallback*>(this), 0, 0L);
  3012.             else
  3013.                 m_spMoniker.Release();
  3014.  
  3015.             if (SUCCEEDED(hr))
  3016.                 hr = m_spMoniker->BindToStorage(m_spBindCtx, 0, IID_IStream, (void**)&spStream);
  3017.         }
  3018.         else
  3019.         {
  3020.             hr = CreateBindCtx(0, &m_spBindCtx);
  3021.             if (SUCCEEDED(hr))
  3022.                 hr = RegisterBindStatusCallback(m_spBindCtx, static_cast<IBindStatusCallback*>(this), 0, 0L);
  3023.  
  3024.             if (SUCCEEDED(hr))
  3025.             {
  3026.                 if (bRelative)
  3027.                     hr = spBindHost->CreateMoniker(bstrURL, m_spBindCtx, &m_spMoniker, 0);
  3028.                 else
  3029.                     hr = CreateURLMoniker(NULL, bstrURL, &m_spMoniker);
  3030.             }
  3031.  
  3032.             if (SUCCEEDED(hr))
  3033.             {
  3034.                 hr = spBindHost->MonikerBindToStorage(m_spMoniker, m_spBindCtx, static_cast<IBindStatusCallback*>(this), IID_IStream, (void**)&spStream);
  3035.                 ATLTRACE2(atlTraceControls,2,_T("Bound"));
  3036.             }
  3037.         }
  3038.         return hr;
  3039.     }
  3040.  
  3041.     HRESULT StartAsyncDownload(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE)
  3042.     {
  3043.         m_pT = pT;
  3044.         m_pFunc = pFunc;
  3045.         return  _StartAsyncDownload(bstrURL, pUnkContainer, bRelative);
  3046.     }
  3047.  
  3048.     static HRESULT Download(T* pT, ATL_PDATAAVAILABLE pFunc, BSTR bstrURL, IUnknown* pUnkContainer = NULL, BOOL bRelative = FALSE)
  3049.     {
  3050.         CComObject<CBindStatusCallback<T> > *pbsc;
  3051.         HRESULT hRes = CComObject<CBindStatusCallback<T> >::CreateInstance(&pbsc);
  3052.         if (FAILED(hRes))
  3053.             return hRes;
  3054.         return pbsc->StartAsyncDownload(pT, pFunc, bstrURL, pUnkContainer, bRelative);
  3055.     }
  3056.  
  3057.     CComPtr<IMoniker> m_spMoniker;
  3058.     CComPtr<IBindCtx> m_spBindCtx;
  3059.     CComPtr<IBinding> m_spBinding;
  3060.     CComPtr<IStream> m_spStream;
  3061.     T* m_pT;
  3062.     ATL_PDATAAVAILABLE m_pFunc;
  3063.     DWORD m_dwTotalRead;
  3064.     DWORD m_dwAvailableToRead;
  3065. };
  3066.  
  3067. #define IMPLEMENT_STOCKPROP(type, fname, pname, dispid) \
  3068.     HRESULT STDMETHODCALLTYPE put_##fname(type pname) \
  3069.     { \
  3070.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
  3071.         T* pT = (T*) this; \
  3072.         if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
  3073.             return S_FALSE; \
  3074.         pT->m_##pname = pname; \
  3075.         pT->m_bRequiresSave = TRUE; \
  3076.         pT->FireOnChanged(dispid); \
  3077.         pT->FireViewChange(); \
  3078.         pT->SendOnDataChange(NULL); \
  3079.         return S_OK; \
  3080.     } \
  3081.     HRESULT STDMETHODCALLTYPE get_##fname(type* p##pname) \
  3082.     { \
  3083.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
  3084.         T* pT = (T*) this; \
  3085.         *p##pname = pT->m_##pname; \
  3086.         return S_OK; \
  3087.     }
  3088.  
  3089. #define IMPLEMENT_BOOL_STOCKPROP(fname, pname, dispid) \
  3090.     HRESULT STDMETHODCALLTYPE put_##fname(VARIANT_BOOL pname) \
  3091.     { \
  3092.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
  3093.         T* pT = (T*) this; \
  3094.         if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
  3095.             return S_FALSE; \
  3096.         pT->m_##pname = pname; \
  3097.         pT->m_bRequiresSave = TRUE; \
  3098.         pT->FireOnChanged(dispid); \
  3099.         pT->FireViewChange(); \
  3100.         pT->SendOnDataChange(NULL); \
  3101.         return S_OK; \
  3102.     } \
  3103.     HRESULT STDMETHODCALLTYPE get_##fname(VARIANT_BOOL* p##pname) \
  3104.     { \
  3105.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
  3106.         T* pT = (T*) this; \
  3107.         *p##pname = pT->m_##pname ? VARIANT_TRUE : VARIANT_FALSE; \
  3108.         return S_OK; \
  3109.     }
  3110.  
  3111. #define IMPLEMENT_BSTR_STOCKPROP(fname, pname, dispid) \
  3112.     HRESULT STDMETHODCALLTYPE put_##fname(BSTR pname) \
  3113.     { \
  3114.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_%s\n"), #fname); \
  3115.         T* pT = (T*) this; \
  3116.         if (pT->FireOnRequestEdit(dispid) == S_FALSE) \
  3117.             return S_FALSE; \
  3118.         if (*(&(pT->m_##pname)) != NULL) \
  3119.             SysFreeString(*(&(pT->m_##pname))); \
  3120.         *(&(pT->m_##pname)) = SysAllocString(pname); \
  3121.         pT->m_bRequiresSave = TRUE; \
  3122.         pT->FireOnChanged(dispid); \
  3123.         pT->FireViewChange(); \
  3124.         pT->SendOnDataChange(NULL); \
  3125.         return S_OK; \
  3126.     } \
  3127.     HRESULT STDMETHODCALLTYPE get_##fname(BSTR* p##pname) \
  3128.     { \
  3129.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_%s\n"), #fname); \
  3130.         T* pT = (T*) this; \
  3131.         *p##pname = SysAllocString(pT->m_##pname); \
  3132.         return S_OK; \
  3133.     }
  3134.  
  3135.  
  3136. template < class T, class InterfaceName, const IID* piid, const GUID* plibid>
  3137. class ATL_NO_VTABLE CStockPropImpl : public IDispatchImpl< InterfaceName, piid, plibid >
  3138. {
  3139. public:
  3140.     // Font
  3141.     HRESULT STDMETHODCALLTYPE put_Font(IFontDisp* pFont)
  3142.     {
  3143.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Font\n"));
  3144.         T* pT = (T*) this;
  3145.         if (pT->FireOnRequestEdit(DISPID_FONT) == S_FALSE)
  3146.             return S_FALSE;
  3147.         pT->m_pFont = 0;
  3148.         if (pFont)
  3149.         {
  3150.             CComQIPtr<IFont, &IID_IFont> p(pFont);
  3151.             if (p)
  3152.             {
  3153.                 CComPtr<IFont> pFont;
  3154.                 p->Clone(&pFont);
  3155.                 if (pFont)
  3156.                     pFont->QueryInterface(IID_IFontDisp, (void**) &pT->m_pFont);
  3157.             }
  3158.         }
  3159.         pT->m_bRequiresSave = TRUE;
  3160.         pT->FireOnChanged(DISPID_FONT);
  3161.         pT->FireViewChange();
  3162.         pT->SendOnDataChange(NULL);
  3163.         return S_OK;
  3164.     }
  3165.     HRESULT STDMETHODCALLTYPE putref_Font(IFontDisp* pFont)
  3166.     {
  3167.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_Font\n"));
  3168.         T* pT = (T*) this;
  3169.         if (pT->FireOnRequestEdit(DISPID_FONT) == S_FALSE)
  3170.             return S_FALSE;
  3171.         pT->m_pFont = pFont;
  3172.         pT->m_bRequiresSave = TRUE;
  3173.         pT->FireOnChanged(DISPID_FONT);
  3174.         pT->FireViewChange();
  3175.         pT->SendOnDataChange(NULL);
  3176.         return S_OK;
  3177.     }
  3178.     HRESULT STDMETHODCALLTYPE get_Font(IFontDisp** ppFont)
  3179.     {
  3180.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Font\n"));
  3181.         T* pT = (T*) this;
  3182.         *ppFont = pT->m_pFont;
  3183.         if (*ppFont != NULL)
  3184.             (*ppFont)->AddRef();
  3185.         return S_OK;
  3186.     }
  3187.     // Picture
  3188.     HRESULT STDMETHODCALLTYPE put_Picture(IPictureDisp* pPicture)
  3189.     {
  3190.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Picture\n"));
  3191.         T* pT = (T*) this;
  3192.         if (pT->FireOnRequestEdit(DISPID_PICTURE) == S_FALSE)
  3193.             return S_FALSE;
  3194.         pT->m_pPicture = 0;
  3195.         if (pPicture)
  3196.         {
  3197.             CComQIPtr<IPersistStream, &IID_IPersistStream> p(pPicture);
  3198.             if (p)
  3199.             {
  3200.                 ULARGE_INTEGER l;
  3201.                 p->GetSizeMax(&l);
  3202.                 HGLOBAL hGlob = GlobalAlloc(GHND, l.LowPart);
  3203.                 if (hGlob)
  3204.                 {
  3205.                     CComPtr<IStream> spStream;
  3206.                     CreateStreamOnHGlobal(hGlob, TRUE, &spStream);
  3207.                     if (spStream)
  3208.                     {
  3209.                         if (SUCCEEDED(p->Save(spStream, FALSE)))
  3210.                         {
  3211.                             LARGE_INTEGER l;
  3212.                             l.QuadPart = 0;
  3213.                             spStream->Seek(l, STREAM_SEEK_SET, NULL);
  3214.                             OleLoadPicture(spStream, l.LowPart, FALSE, IID_IPictureDisp, (void**)&pT->m_pPicture);
  3215.                         }
  3216.                         spStream.Release();
  3217.                     }
  3218.                     GlobalFree(hGlob);
  3219.                 }
  3220.             }
  3221.         }
  3222.         pT->m_bRequiresSave = TRUE;
  3223.         pT->FireOnChanged(DISPID_PICTURE);
  3224.         pT->FireViewChange();
  3225.         pT->SendOnDataChange(NULL);
  3226.         return S_OK;
  3227.     }
  3228.     HRESULT STDMETHODCALLTYPE putref_Picture(IPictureDisp* pPicture)
  3229.     {
  3230.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_Picture\n"));
  3231.         T* pT = (T*) this;
  3232.         if (pT->FireOnRequestEdit(DISPID_PICTURE) == S_FALSE)
  3233.             return S_FALSE;
  3234.         pT->m_pPicture = pPicture;
  3235.         pT->m_bRequiresSave = TRUE;
  3236.         pT->FireOnChanged(DISPID_PICTURE);
  3237.         pT->FireViewChange();
  3238.         pT->SendOnDataChange(NULL);
  3239.         return S_OK;
  3240.     }
  3241.     HRESULT STDMETHODCALLTYPE get_Picture(IPictureDisp** ppPicture)
  3242.     {
  3243.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Picture\n"));
  3244.         T* pT = (T*) this;
  3245.         *ppPicture = pT->m_pPicture;
  3246.         if (*ppPicture != NULL)
  3247.             (*ppPicture)->AddRef();
  3248.         return S_OK;
  3249.     }
  3250.     // MouseIcon
  3251.     HRESULT STDMETHODCALLTYPE put_MouseIcon(IPictureDisp* pPicture)
  3252.     {
  3253.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_MouseIcon\n"));
  3254.         T* pT = (T*) this;
  3255.         if (pT->FireOnRequestEdit(DISPID_MOUSEICON) == S_FALSE)
  3256.             return S_FALSE;
  3257.         pT->m_pMouseIcon = 0;
  3258.         if (pPicture)
  3259.         {
  3260.             CComQIPtr<IPersistStream, &IID_IPersistStream> p(pPicture);
  3261.             if (p)
  3262.             {
  3263.                 ULARGE_INTEGER l;
  3264.                 p->GetSizeMax(&l);
  3265.                 HGLOBAL hGlob = GlobalAlloc(GHND, l.LowPart);
  3266.                 if (hGlob)
  3267.                 {
  3268.                     CComPtr<IStream> spStream;
  3269.                     CreateStreamOnHGlobal(hGlob, TRUE, &spStream);
  3270.                     if (spStream)
  3271.                     {
  3272.                         if (SUCCEEDED(p->Save(spStream, FALSE)))
  3273.                         {
  3274.                             LARGE_INTEGER l;
  3275.                             l.QuadPart = 0;
  3276.                             spStream->Seek(l, STREAM_SEEK_SET, NULL);
  3277.                             OleLoadPicture(spStream, l.LowPart, FALSE, IID_IPictureDisp, (void**)&pT->m_pMouseIcon);
  3278.                         }
  3279.                         spStream.Release();
  3280.                     }
  3281.                     GlobalFree(hGlob);
  3282.                 }
  3283.             }
  3284.         }
  3285.         pT->m_bRequiresSave = TRUE;
  3286.         pT->FireOnChanged(DISPID_MOUSEICON);
  3287.         pT->FireViewChange();
  3288.         pT->SendOnDataChange(NULL);
  3289.         return S_OK;
  3290.     }
  3291.     HRESULT STDMETHODCALLTYPE putref_MouseIcon(IPictureDisp* pPicture)
  3292.     {
  3293.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::putref_MouseIcon\n"));
  3294.         T* pT = (T*) this;
  3295.         if (pT->FireOnRequestEdit(DISPID_MOUSEICON) == S_FALSE)
  3296.             return S_FALSE;
  3297.         pT->m_pMouseIcon = pPicture;
  3298.         pT->m_bRequiresSave = TRUE;
  3299.         pT->FireOnChanged(DISPID_MOUSEICON);
  3300.         pT->FireViewChange();
  3301.         pT->SendOnDataChange(NULL);
  3302.         return S_OK;
  3303.     }
  3304.     HRESULT STDMETHODCALLTYPE get_MouseIcon(IPictureDisp** ppPicture)
  3305.     {
  3306.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_MouseIcon\n"));
  3307.         T* pT = (T*) this;
  3308.         *ppPicture = pT->m_pMouseIcon;
  3309.         if (*ppPicture != NULL)
  3310.             (*ppPicture)->AddRef();
  3311.         return S_OK;
  3312.     }
  3313.     IMPLEMENT_STOCKPROP(OLE_COLOR, BackColor, clrBackColor, DISPID_BACKCOLOR)
  3314.     IMPLEMENT_STOCKPROP(OLE_COLOR, BorderColor, clrBorderColor, DISPID_BORDERCOLOR)
  3315.     IMPLEMENT_STOCKPROP(OLE_COLOR, FillColor, clrFillColor, DISPID_FILLCOLOR)
  3316.     IMPLEMENT_STOCKPROP(OLE_COLOR, ForeColor, clrForeColor, DISPID_FORECOLOR)
  3317.     IMPLEMENT_BOOL_STOCKPROP(AutoSize, bAutoSize, DISPID_AUTOSIZE)
  3318.     IMPLEMENT_BOOL_STOCKPROP(Valid, bValid, DISPID_VALID)
  3319.     IMPLEMENT_BOOL_STOCKPROP(Enabled, bEnabled, DISPID_ENABLED)
  3320.     IMPLEMENT_BOOL_STOCKPROP(TabStop, bTabStop, DISPID_TABSTOP)
  3321.     IMPLEMENT_BOOL_STOCKPROP(BorderVisible, bBorderVisible, DISPID_BORDERVISIBLE)
  3322.     IMPLEMENT_BSTR_STOCKPROP(Text, bstrText, DISPID_TEXT)
  3323.     IMPLEMENT_BSTR_STOCKPROP(Caption, bstrCaption, DISPID_CAPTION)
  3324.     HRESULT STDMETHODCALLTYPE put_Window(long /*hWnd*/)
  3325.     {
  3326.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::put_Window\n"));
  3327.         return E_FAIL;
  3328.     }
  3329.     HRESULT STDMETHODCALLTYPE get_Window(long* phWnd)
  3330.     {
  3331.         ATLTRACE2(atlTraceControls,2,_T("CStockPropImpl::get_Window\n"));
  3332.         T* pT = (T*) this;
  3333.         *phWnd = (long)pT->m_hWnd;
  3334.         return S_OK;
  3335.     }
  3336.     IMPLEMENT_STOCKPROP(LONG, BackStyle, nBackStyle, DISPID_BACKSTYLE)
  3337.     IMPLEMENT_STOCKPROP(LONG, BorderStyle, nBorderStyle, DISPID_BORDERSTYLE)
  3338.     IMPLEMENT_STOCKPROP(LONG, BorderWidth, nBorderWidth, DISPID_BORDERWIDTH)
  3339.     IMPLEMENT_STOCKPROP(LONG, DrawMode, nDrawMode, DISPID_DRAWMODE)
  3340.     IMPLEMENT_STOCKPROP(LONG, DrawStyle, nDrawStyle, DISPID_DRAWSTYLE)
  3341.     IMPLEMENT_STOCKPROP(LONG, DrawWidth, nDrawWidth, DISPID_DRAWWIDTH)
  3342.     IMPLEMENT_STOCKPROP(LONG, FillStyle, nFillStyle, DISPID_FILLSTYLE)
  3343.     IMPLEMENT_STOCKPROP(SHORT, Appearance, nAppearance, DISPID_APPEARANCE)
  3344.     IMPLEMENT_STOCKPROP(LONG, MousePointer, nMousePointer, DISPID_MOUSEPOINTER)
  3345.     IMPLEMENT_STOCKPROP(LONG, ReadyState, nReadyState, DISPID_READYSTATE)
  3346. };
  3347.  
  3348. #pragma pack(pop)
  3349.  
  3350. }; //namespace ATL
  3351.  
  3352. #ifndef _ATL_DLL_IMPL
  3353. #ifndef _ATL_DLL
  3354. #define _ATLCTL_IMPL
  3355. #endif
  3356. #endif
  3357.  
  3358. #endif // __ATLCTL_H__
  3359.  
  3360. #ifdef _ATLCTL_IMPL
  3361.  
  3362. #ifndef _ATL_DLL_IMPL
  3363. namespace ATL
  3364. {
  3365. #endif
  3366.  
  3367.  
  3368. //All exports go here
  3369.  
  3370.  
  3371. #ifndef _ATL_DLL_IMPL
  3372. }; //namespace ATL
  3373. #endif
  3374.  
  3375. //Prevent pulling in second time 
  3376. #undef _ATLCTL_IMPL
  3377.  
  3378. #endif // _ATLCTL_IMPL
  3379.  
  3380.