home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / occcont.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  19KB  |  792 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12. #include "occimpl.h"
  13.  
  14. #ifdef AFX_OCC_SEG
  15. #pragma code_seg(AFX_OCC_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // CWnd support for OLE Control containment
  27.  
  28. BOOL CWnd::CreateControl(LPCTSTR lpszClass, LPCTSTR lpszWindowName,
  29.     DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
  30.     CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  31. {
  32.     ASSERT(lpszClass != NULL);
  33.  
  34.     CLSID clsid;
  35.     HRESULT hr = AfxGetClassIDFromString(lpszClass, &clsid);
  36.     if (FAILED(hr))
  37.         return FALSE;
  38.  
  39.     return CreateControl(clsid, lpszWindowName, dwStyle, rect, pParentWnd, nID,
  40.         pPersist, bStorage, bstrLicKey);
  41. }
  42.  
  43. BOOL CWnd::CreateControl( REFCLSID clsid, LPCTSTR lpszWindowName,
  44.    DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID,
  45.    CFile* pPersist, BOOL bStorage, BSTR bstrLicKey )
  46. {
  47.    CRect rect2( rect );
  48.    CPoint pt;
  49.    CSize size;
  50.  
  51.    pt = rect2.TopLeft();
  52.    size = rect2.Size();
  53.  
  54.    return( CreateControl( clsid, lpszWindowName, dwStyle, &pt, &size,
  55.       pParentWnd, nID, pPersist, bStorage, bstrLicKey ) );
  56. }
  57.  
  58. BOOL CWnd::CreateControl(REFCLSID clsid, LPCTSTR lpszWindowName, DWORD dwStyle,
  59.     const POINT* ppt, const SIZE* psize, CWnd* pParentWnd, UINT nID,
  60.    CFile* pPersist, BOOL bStorage, BSTR bstrLicKey)
  61. {
  62.     ASSERT(pParentWnd != NULL);
  63.  
  64. #ifdef _DEBUG
  65.     if (afxOccManager == NULL)
  66.     {
  67.         TRACE0("Warning: AfxEnableControlContainer has not been called yet.\n");
  68.         TRACE0(">>> You should call it in your app's InitInstance function.\n");
  69.     }
  70. #endif
  71.  
  72.     if ((pParentWnd == NULL) || !pParentWnd->InitControlContainer())
  73.         return FALSE;
  74.  
  75.     return pParentWnd->m_pCtrlCont->CreateControl(this, clsid, lpszWindowName,
  76.         dwStyle, ppt, psize, nID, pPersist, bStorage, bstrLicKey);
  77. }
  78.  
  79. BOOL CWnd::InitControlContainer()
  80. {
  81.     TRY
  82.     {
  83.         if (m_pCtrlCont == NULL)
  84.             m_pCtrlCont = afxOccManager->CreateContainer(this);
  85.     }
  86.     END_TRY
  87.  
  88.     // Mark all ancestor windows as containing OLE controls.
  89.     if (m_pCtrlCont != NULL)
  90.     {
  91.         CWnd* pWnd = this;
  92.         while ((pWnd != NULL) && !(pWnd->m_nFlags & WF_OLECTLCONTAINER))
  93.         {
  94.             pWnd->m_nFlags |= WF_OLECTLCONTAINER;
  95.             pWnd = pWnd->GetParent();
  96.             if (! (GetWindowLong(pWnd->GetSafeHwnd(), GWL_STYLE) & WS_CHILD))
  97.                 break;
  98.         }
  99.     }
  100.  
  101.     return (m_pCtrlCont != NULL);
  102. }
  103.  
  104. /////////////////////////////////////////////////////////////////////////////
  105. // COleControlContainer
  106.  
  107. BEGIN_INTERFACE_MAP(COleControlContainer, CCmdTarget)
  108.     INTERFACE_PART(COleControlContainer, IID_IOleInPlaceFrame, OleIPFrame)
  109.     INTERFACE_PART(COleControlContainer, IID_IOleContainer, OleContainer)
  110. END_INTERFACE_MAP()
  111.  
  112. BEGIN_DISPATCH_MAP(COleControlContainer, CCmdTarget)
  113. END_DISPATCH_MAP()
  114.  
  115. COleControlContainer::COleControlContainer(CWnd* pWnd) :
  116.     m_pWnd(pWnd),
  117.     m_crBack((COLORREF)-1),
  118.     m_crFore((COLORREF)-1),
  119.     m_pOleFont(NULL),
  120.     m_pSiteUIActive(NULL)
  121. {
  122. }
  123.  
  124. COleControlContainer::~COleControlContainer()
  125. {
  126.     HWND hWnd;
  127.     COleControlSite* pSite;
  128.     POSITION pos = m_siteMap.GetStartPosition();
  129.     while (pos != NULL)
  130.     {
  131.         m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  132.         if (!(pSite->m_pDataSourceControl))
  133.         {
  134.             m_siteMap.RemoveKey((void*&)hWnd);
  135.             delete pSite;
  136.         }
  137.     }
  138.  
  139.     pos = m_siteMap.GetStartPosition();
  140.     while (pos != NULL)
  141.     {
  142.         m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  143.         delete pSite;
  144.     }
  145.     m_siteMap.RemoveAll();
  146.  
  147.     RELEASE(m_pOleFont);
  148. }
  149.  
  150. BOOL COleControlContainer::CreateControl( CWnd* pWndCtrl, REFCLSID clsid,
  151.     LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, UINT nID,
  152.     CFile* pPersist, BOOL bStorage, BSTR bstrLicKey,
  153.     COleControlSite** ppNewSite )
  154. {
  155.    CRect rect2( rect );
  156.    CPoint pt;
  157.    CSize size;
  158.  
  159.    pt = rect2.TopLeft();
  160.    size = rect2.Size();
  161.  
  162.    return( CreateControl( pWndCtrl, clsid, lpszWindowName, dwStyle, &pt, &size,
  163.       nID, pPersist, bStorage, bstrLicKey, ppNewSite ) );
  164. }
  165.  
  166. BOOL COleControlContainer::CreateControl(CWnd* pWndCtrl, REFCLSID clsid,
  167.     LPCTSTR lpszWindowName, DWORD dwStyle, const POINT* ppt, const SIZE* psize,
  168.    UINT nID, CFile* pPersist, BOOL bStorage, BSTR bstrLicKey,
  169.    COleControlSite** ppNewSite)
  170. {
  171.     COleControlSite* pSite = NULL;
  172.  
  173.     TRY
  174.     {
  175.         pSite = afxOccManager->CreateSite(this);
  176.     }
  177.     END_TRY
  178.  
  179.     if (pSite == NULL)
  180.         return FALSE;
  181.  
  182.     BOOL bCreated = SUCCEEDED( pSite->CreateControl(pWndCtrl, clsid,
  183.         lpszWindowName, dwStyle, ppt, psize, nID, pPersist, bStorage,
  184.       bstrLicKey ) );
  185.  
  186.     if (bCreated)
  187.     {
  188.         ASSERT(pSite->m_hWnd != NULL);
  189.         m_siteMap.SetAt(pSite->m_hWnd, pSite);
  190.         if (ppNewSite != NULL)
  191.             *ppNewSite = pSite;
  192.     }
  193.     else
  194.     {
  195.         delete pSite;
  196.     }
  197.  
  198.     return bCreated;
  199. }
  200.  
  201. COleControlSite* COleControlContainer::FindItem(UINT nID) const
  202. {
  203.     POSITION pos = m_siteMap.GetStartPosition();
  204.     while (pos != NULL)
  205.     {
  206.         HWND hWnd;
  207.         COleControlSite* pSite;
  208.         m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  209.         if (pSite->GetID() == nID)
  210.             return pSite;
  211.     }
  212.     return NULL;
  213. }
  214.  
  215. BOOL COleControlContainer::GetAmbientProp(COleControlSite* pSite, DISPID dispid,
  216.     VARIANT* pvarResult)
  217. {
  218.     switch (dispid)
  219.     {
  220.     case DISPID_AMBIENT_AUTOCLIP:
  221.     case DISPID_AMBIENT_MESSAGEREFLECT:
  222.     case DISPID_AMBIENT_SUPPORTSMNEMONICS:
  223.     case DISPID_AMBIENT_USERMODE:
  224.         V_VT(pvarResult) = VT_BOOL;
  225.         V_BOOL(pvarResult) = (VARIANT_BOOL)-1;
  226.         return TRUE;
  227.  
  228.     case DISPID_AMBIENT_SHOWGRABHANDLES:
  229.     case DISPID_AMBIENT_SHOWHATCHING:
  230.     case DISPID_AMBIENT_UIDEAD:
  231.         V_VT(pvarResult) = VT_BOOL;
  232.         V_BOOL(pvarResult) = 0;
  233.         return TRUE;
  234.  
  235.     case DISPID_AMBIENT_APPEARANCE:     // ambient appearance is 3D
  236.         V_VT(pvarResult) = VT_I2;
  237. #ifndef _AFX_NO_CTL3D_SUPPORT
  238.         if (afxData.bWin4 || AfxGetCtl3dState()->m_pfnSubclassDlgEx != NULL)
  239. #else
  240.         if (afxData.bWin4)
  241. #endif
  242.             V_I2(pvarResult) = 1;
  243.         else
  244.             V_I2(pvarResult) = 0;
  245.         return TRUE;
  246.  
  247.     case DISPID_AMBIENT_BACKCOLOR:
  248.     case DISPID_AMBIENT_FORECOLOR:
  249.         if (m_crBack == (COLORREF)-1)   // ambient colors not initialized
  250.         {
  251.             CWindowDC dc(m_pWnd);
  252.             m_pWnd->SendMessage(WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC,
  253.                 (LPARAM)m_pWnd->m_hWnd);
  254.             m_crBack = dc.GetBkColor();
  255.             m_crFore = dc.GetTextColor();
  256.         }
  257.  
  258.         V_VT(pvarResult) = VT_COLOR;
  259.         V_I4(pvarResult) = (dispid == DISPID_AMBIENT_BACKCOLOR) ?
  260.             m_crBack : m_crFore;
  261.         return TRUE;
  262.  
  263.     case DISPID_AMBIENT_FONT:
  264.         if (m_pOleFont == NULL)         // ambient font not initialized
  265.             CreateOleFont(m_pWnd->GetFont());
  266.  
  267.         ASSERT(m_pOleFont != NULL);
  268.         if (m_pOleFont == NULL)         // failed to create font
  269.             return FALSE;
  270.  
  271.         V_VT(pvarResult) = VT_FONT;
  272.         m_pOleFont->AddRef();
  273.         V_DISPATCH(pvarResult) = m_pOleFont;
  274.         return TRUE;
  275.  
  276.     case DISPID_AMBIENT_DISPLAYASDEFAULT:
  277.         V_VT(pvarResult) = VT_BOOL;
  278.         V_BOOL(pvarResult) = (VARIANT_BOOL)(pSite->IsDefaultButton() ? -1 : 0);
  279.         return TRUE;
  280.  
  281.     case DISPID_AMBIENT_LOCALEID:
  282.         V_VT(pvarResult) = VT_I4;
  283.         V_I4(pvarResult) = GetThreadLocale();
  284.         return TRUE;
  285.  
  286.     case DISPID_AMBIENT_DISPLAYNAME:
  287.         {
  288.             CString str;                // return blank string
  289.             V_VT(pvarResult) = VT_BSTR;
  290.             V_BSTR(pvarResult) = str.AllocSysString();
  291.         }
  292.         return TRUE;
  293.  
  294.     case DISPID_AMBIENT_SCALEUNITS:
  295.         {
  296.             CString str;
  297.             str.LoadString(AFX_IDS_OCC_SCALEUNITS_PIXELS);
  298.             V_VT(pvarResult) = VT_BSTR;
  299.             V_BSTR(pvarResult) = str.AllocSysString();
  300.         }
  301.         return TRUE;
  302.     }
  303.  
  304.     return FALSE;
  305. }
  306.  
  307. void COleControlContainer::CreateOleFont(CFont* pFont)
  308. {
  309.     USES_CONVERSION;
  310.  
  311.     CFont fontSys;
  312.     if ((pFont == NULL) || (pFont->m_hObject == NULL))
  313.     {
  314.         // no font was provided, so use the system font
  315.         if (fontSys.CreateStockObject(DEFAULT_GUI_FONT) ||
  316.             fontSys.CreateStockObject(SYSTEM_FONT))
  317.         {
  318.             pFont = &fontSys;
  319.         }
  320.         else
  321.         {
  322.             m_pOleFont = NULL;
  323.             return;
  324.         }
  325.     }
  326.  
  327.     LOGFONT logfont;
  328.     pFont->GetLogFont(&logfont);
  329.  
  330.     FONTDESC fd;
  331.     fd.cbSizeofstruct = sizeof(FONTDESC);
  332.     fd.lpstrName = T2OLE(logfont.lfFaceName);
  333.     fd.sWeight = (short)logfont.lfWeight;
  334.     fd.sCharset = logfont.lfCharSet;
  335.     fd.fItalic = logfont.lfItalic;
  336.     fd.fUnderline = logfont.lfUnderline;
  337.     fd.fStrikethrough = logfont.lfStrikeOut;
  338.  
  339.     long lfHeight = logfont.lfHeight;
  340.     if (lfHeight < 0)
  341.         lfHeight = -lfHeight;
  342.  
  343.     CWindowDC dc(m_pWnd);
  344.     int ppi = dc.GetDeviceCaps(LOGPIXELSY);
  345.     fd.cySize.Lo = lfHeight * 720000 / ppi;
  346.     fd.cySize.Hi = 0;
  347.  
  348.     RELEASE(m_pOleFont);
  349.     if (FAILED(::OleCreateFontIndirect(&fd, IID_IFontDisp, (void**)&m_pOleFont)))
  350.         m_pOleFont = NULL;
  351. }
  352.  
  353. void COleControlContainer::FreezeAllEvents(BOOL bFreeze)
  354. {
  355.     HWND hWnd;
  356.     COleControlSite* pSite;
  357.     POSITION pos = m_siteMap.GetStartPosition();
  358.     while (pos != NULL)
  359.     {
  360.         m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  361.         pSite->FreezeEvents(bFreeze);
  362.     }
  363. }
  364.  
  365. void COleControlContainer::ScrollChildren(int dx, int dy)
  366. {
  367.     HWND hWnd;
  368.     COleControlSite* pSite;
  369.     POSITION pos = m_siteMap.GetStartPosition();
  370.     while (pos != NULL)
  371.     {
  372.         m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  373.         ASSERT(pSite->m_pInPlaceObject != NULL);
  374.         ASSERT(pSite->m_pObject != NULL);
  375.         pSite->m_rect.OffsetRect(dx, dy);
  376.         pSite->m_pInPlaceObject->SetObjectRects(pSite->m_rect, pSite->m_rect);
  377.     }
  378. }
  379.  
  380. void COleControlContainer::OnUIActivate(COleControlSite* pSite)
  381. {
  382.     if (m_pSiteUIActive != NULL)
  383.         m_pSiteUIActive->m_pInPlaceObject->UIDeactivate();
  384.  
  385.     ASSERT(m_pSiteUIActive == NULL);    // did control call OnUIDeactivate?
  386.     m_pSiteUIActive = pSite;
  387. }
  388.  
  389. void COleControlContainer::OnUIDeactivate(COleControlSite* pSite)
  390. {
  391.     UNUSED(pSite);
  392.  
  393.     if (m_pSiteUIActive == pSite)
  394.         m_pSiteUIActive = NULL;
  395. }
  396.  
  397. /////////////////////////////////////////////////////////////////////////////
  398. // special cases for CWnd functions
  399.  
  400. void COleControlContainer::CheckDlgButton(int nIDButton, UINT nCheck)
  401. {
  402.     CWnd* pWnd = GetDlgItem(nIDButton);
  403.     if (pWnd == NULL)
  404.         return;
  405.  
  406.     if (pWnd->m_pCtrlSite == NULL)
  407.     {
  408.         pWnd->SendMessage(BM_SETCHECK, nCheck, 0);
  409.         return;
  410.     }
  411.  
  412.     pWnd->m_pCtrlSite->SafeSetProperty(DISPID_VALUE, VT_I4, (DWORD)nCheck);
  413. }
  414.  
  415. void COleControlContainer::CheckRadioButton(int nIDFirstButton, int nIDLastButton,
  416.     int nIDCheckButton)
  417. {
  418.     ASSERT(nIDFirstButton <= nIDCheckButton);
  419.     ASSERT(nIDCheckButton <= nIDLastButton);
  420.  
  421.     // the following code is for OLE control containers only
  422.     for (int nID = nIDFirstButton; nID <= nIDLastButton; nID++)
  423.         CheckDlgButton(nID, (nID == nIDCheckButton));
  424. }
  425.  
  426. CWnd* COleControlContainer::GetDlgItem(int nID) const
  427. {
  428.     HWND hWnd;
  429.     GetDlgItem(nID, &hWnd);
  430.     return CWnd::FromHandle(hWnd);
  431. }
  432.  
  433. void COleControlContainer::GetDlgItem(int nID, HWND* phWnd) const
  434. {
  435.     // first, look for a non-OLE control
  436.     HWND hWnd = ::GetDlgItem(m_pWnd->GetSafeHwnd(), nID);
  437.     if (hWnd == NULL)
  438.     {
  439.         // now, look for an OLE control
  440.         COleControlSite* pSite = FindItem(nID);
  441.         if (pSite != NULL)
  442.             hWnd = pSite->m_hWnd;
  443.     }
  444.  
  445.     *phWnd = hWnd;
  446. }
  447.  
  448. UINT COleControlContainer::GetDlgItemInt(int nID, BOOL* lpTrans, BOOL bSigned) const
  449. {
  450.     TCHAR szText[256];
  451.     if (GetDlgItemText(nID, szText, 256) == 0)
  452.     {
  453.         if (lpTrans != NULL)
  454.             *lpTrans = FALSE;
  455.         return 0;
  456.     }
  457.  
  458.     // Quick check for valid number
  459.     LPTSTR pch = szText;
  460.  
  461.     while (_istspace(*pch))
  462.         pch = CharNext(pch);    // skip whitespace
  463.  
  464.     if ((*pch) == '+' || (*pch) == '-')
  465.         pch = CharNext(pch);    // skip sign
  466.  
  467.     BOOL bTrans = _istdigit(*pch);    // did we find a digit?
  468.  
  469.     if (lpTrans != NULL)
  470.         *lpTrans = bTrans;
  471.  
  472.     if (!bTrans)
  473.         return 0;
  474.  
  475.     if (bSigned)
  476.         return _tcstol(szText, NULL, 10);
  477.     else
  478.         return _tcstoul(szText, NULL, 10);
  479. }
  480.  
  481. int COleControlContainer::GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const
  482. {
  483.     CWnd* pWnd = GetDlgItem(nID);
  484.     if (pWnd == NULL)
  485.         return 0;
  486.  
  487.     return pWnd->GetWindowText(lpStr, nMaxCount);
  488. }
  489.  
  490. LRESULT COleControlContainer::SendDlgItemMessage(int nID, UINT message, WPARAM wParam,
  491.     LPARAM lParam)
  492. {
  493.     CWnd* pWnd = GetDlgItem(nID);
  494.     if (pWnd == NULL)
  495.         return 0;
  496.  
  497.     return pWnd->SendMessage(message, wParam, lParam);
  498. }
  499.  
  500. void COleControlContainer::SetDlgItemInt(int nID, UINT nValue, BOOL bSigned)
  501. {
  502.     TCHAR szText[34];
  503.     if (bSigned)
  504.         _ltot((long)nValue, szText, 10);
  505.     else
  506.         _ultot((unsigned long)nValue, szText, 10);
  507.  
  508.     SetDlgItemText(nID, szText);
  509. }
  510.  
  511. void COleControlContainer::SetDlgItemText(int nID, LPCTSTR lpszString)
  512. {
  513.     CWnd* pWnd = GetDlgItem(nID);
  514.     if (pWnd == NULL)
  515.         return;
  516.  
  517.     pWnd->SetWindowText(lpszString);
  518. }
  519.  
  520. UINT COleControlContainer::IsDlgButtonChecked(int nIDButton) const
  521. {
  522.     CWnd* pWnd = GetDlgItem(nIDButton);
  523.     if (pWnd == NULL)
  524.         return 0;
  525.  
  526.     if (pWnd->m_pCtrlSite == NULL)
  527.         return pWnd->SendMessage(BM_GETCHECK, 0, 0);
  528.  
  529.     DWORD dwValue;
  530.  
  531.     TRY
  532.     {
  533.         pWnd->GetProperty(DISPID_VALUE, VT_I4, &dwValue);
  534.     }
  535.     CATCH_ALL(e)
  536.     {
  537.         DELETE_EXCEPTION(e);
  538.         dwValue = 0;
  539.     }
  540.     END_CATCH_ALL
  541.  
  542.     if (dwValue == 0x0000ffff)  // VARIANT_BOOL TRUE
  543.         dwValue = 1;
  544.  
  545.     return dwValue;
  546. }
  547.  
  548. /////////////////////////////////////////////////////////////////////////////
  549. // COleControlContainer::XOleIPFrame
  550.  
  551. STDMETHODIMP COleControlContainer::XOleIPFrame::QueryInterface(
  552.     REFIID iid, LPVOID* ppvObj)
  553. {
  554.     METHOD_PROLOGUE_EX_(COleControlContainer, OleIPFrame)
  555.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  556. }
  557.  
  558. STDMETHODIMP_(ULONG) COleControlContainer::XOleIPFrame::AddRef()
  559. {
  560.     METHOD_PROLOGUE_EX_(COleControlContainer, OleIPFrame)
  561.     return (ULONG)pThis->InternalAddRef();
  562. }
  563.  
  564. STDMETHODIMP_(ULONG) COleControlContainer::XOleIPFrame::Release()
  565. {
  566.     METHOD_PROLOGUE_EX_(COleControlContainer, OleIPFrame)
  567.     return (ULONG)pThis->InternalRelease();
  568. }
  569.  
  570. STDMETHODIMP COleControlContainer::XOleIPFrame::GetWindow(HWND* phWnd)
  571. {
  572.     METHOD_PROLOGUE_EX_(COleControlContainer, OleIPFrame)
  573.  
  574.     *phWnd = pThis->m_pWnd->m_hWnd;
  575.     return S_OK;
  576. }
  577.  
  578. STDMETHODIMP COleControlContainer::XOleIPFrame::ContextSensitiveHelp(BOOL)
  579. {
  580.     return E_NOTIMPL;
  581. }
  582.  
  583. STDMETHODIMP COleControlContainer::XOleIPFrame::GetBorder(LPRECT)
  584. {
  585.     return E_NOTIMPL;
  586. }
  587.  
  588. STDMETHODIMP COleControlContainer::XOleIPFrame::RequestBorderSpace(
  589.     LPCBORDERWIDTHS)
  590. {
  591.     return E_NOTIMPL;
  592. }
  593.  
  594. STDMETHODIMP COleControlContainer::XOleIPFrame::SetBorderSpace(
  595.     LPCBORDERWIDTHS)
  596. {
  597.     return E_NOTIMPL;
  598. }
  599.  
  600. STDMETHODIMP COleControlContainer::XOleIPFrame::SetActiveObject(
  601.     LPOLEINPLACEACTIVEOBJECT pActiveObject, LPCOLESTR)
  602. {
  603.     METHOD_PROLOGUE_EX_(COleControlContainer, OleIPFrame)
  604.  
  605.     if (pThis->m_pSiteUIActive != NULL)
  606.     {
  607.         LPOLEINPLACEACTIVEOBJECT pOldActiveObject = pThis->m_pSiteUIActive->m_pActiveObject;
  608.         if (pActiveObject != NULL)
  609.             pActiveObject->AddRef();
  610.         pThis->m_pSiteUIActive->m_pActiveObject = pActiveObject;
  611.         if (pOldActiveObject != NULL)
  612.             pOldActiveObject->Release();
  613.     }
  614.     return S_OK;
  615. }
  616.  
  617. STDMETHODIMP COleControlContainer::XOleIPFrame::InsertMenus(HMENU,
  618.     LPOLEMENUGROUPWIDTHS)
  619. {
  620.     return E_NOTIMPL;
  621. }
  622.  
  623. STDMETHODIMP COleControlContainer::XOleIPFrame::SetMenu(HMENU, HOLEMENU, HWND)
  624. {
  625.     return E_NOTIMPL;
  626. }
  627.  
  628. STDMETHODIMP COleControlContainer::XOleIPFrame::RemoveMenus(HMENU)
  629. {
  630.     return E_NOTIMPL;
  631. }
  632.  
  633. STDMETHODIMP COleControlContainer::XOleIPFrame::SetStatusText(LPCOLESTR)
  634. {
  635.     return E_NOTIMPL;
  636. }
  637.  
  638. STDMETHODIMP COleControlContainer::XOleIPFrame::EnableModeless(BOOL)
  639. {
  640.    // As long as we don't create any modeless dialogs, we can just return S_OK.
  641.     return S_OK;
  642. }
  643.  
  644. STDMETHODIMP COleControlContainer::XOleIPFrame::TranslateAccelerator(LPMSG,
  645.     WORD)
  646. {
  647.     return E_NOTIMPL;
  648. }
  649.  
  650. /////////////////////////////////////////////////////////////////////////////
  651. // CEnumUnknown - enumerator for IUnknown pointers
  652.  
  653. class CEnumUnknown : public CEnumArray
  654. {
  655. public:
  656.     CEnumUnknown(const void* pvEnum, UINT nSize) :
  657.         CEnumArray(sizeof(LPUNKNOWN), pvEnum, nSize, TRUE) {}
  658.     ~CEnumUnknown();
  659.  
  660. protected:
  661.     virtual BOOL OnNext(void* pv);
  662.  
  663.     DECLARE_INTERFACE_MAP()
  664. };
  665.  
  666. BEGIN_INTERFACE_MAP(CEnumUnknown, CEnumArray)
  667.     INTERFACE_PART(CEnumUnknown, IID_IEnumUnknown, EnumVOID)
  668. END_INTERFACE_MAP()
  669.  
  670. CEnumUnknown::~CEnumUnknown()
  671. {
  672.     if (m_pClonedFrom == NULL)
  673.     {
  674.         LPUNKNOWN* ppUnk = (LPUNKNOWN*)(void*)m_pvEnum;
  675.         for (UINT i = 0; i < m_nSize; i++)
  676.         {
  677.             ASSERT(ppUnk[i] != NULL);
  678.             ppUnk[i]->Release();
  679.         }
  680.     }
  681.     // destructor will free the actual array (if it was not a clone)
  682. }
  683.  
  684. BOOL CEnumUnknown::OnNext(void* pv)
  685. {
  686.     if (!CEnumArray::OnNext(pv))
  687.         return FALSE;
  688.  
  689.     // AddRef the pointer (the caller has responsibility to Release it)
  690.     ASSERT(*(LPUNKNOWN*)pv != NULL);
  691.     (*(LPUNKNOWN*)pv)->AddRef();
  692.  
  693.     return TRUE;
  694. }
  695.  
  696. /////////////////////////////////////////////////////////////////////////////
  697. // COleControlContainer::XOleContainer
  698.  
  699. STDMETHODIMP COleControlContainer::XOleContainer::QueryInterface(
  700.     REFIID iid, LPVOID* ppvObj)
  701. {
  702.     METHOD_PROLOGUE_EX_(COleControlContainer, OleContainer)
  703.     return (HRESULT)pThis->InternalQueryInterface(&iid, ppvObj);
  704. }
  705.  
  706. STDMETHODIMP_(ULONG) COleControlContainer::XOleContainer::Release()
  707. {
  708.     METHOD_PROLOGUE_EX_(COleControlContainer, OleContainer)
  709.     return (ULONG)pThis->InternalRelease();
  710. }
  711.  
  712. STDMETHODIMP_(ULONG) COleControlContainer::XOleContainer::AddRef()
  713. {
  714.     METHOD_PROLOGUE_EX_(COleControlContainer, OleContainer)
  715.     return (ULONG)pThis->InternalAddRef();
  716. }
  717.  
  718. STDMETHODIMP COleControlContainer::XOleContainer::ParseDisplayName(LPBINDCTX,
  719.     LPOLESTR, ULONG*, LPMONIKER*)
  720. {
  721.     return E_NOTIMPL;
  722. }
  723.  
  724. STDMETHODIMP COleControlContainer::XOleContainer::EnumObjects(DWORD dwFlags,
  725.     LPENUMUNKNOWN* ppEnumUnknown)
  726. {
  727.     METHOD_PROLOGUE_EX_(COleControlContainer, OleContainer)
  728.  
  729.     *ppEnumUnknown = NULL;
  730.     HRESULT hr = S_OK;
  731.     CEnumUnknown* pEnum = NULL;
  732.     UINT cObjects = 0;
  733.     LPUNKNOWN* ppUnk = NULL;
  734.  
  735.     TRY
  736.     {
  737.         if (dwFlags & OLECONTF_EMBEDDINGS)
  738.         {
  739.             cObjects = pThis->m_siteMap.GetCount();
  740.             ppUnk = new LPUNKNOWN[cObjects];
  741.             UINT i = 0;
  742.             POSITION pos = pThis->m_siteMap.GetStartPosition();
  743.             HWND hWnd;
  744.             COleControlSite* pSite;
  745.             while (pos != NULL)
  746.             {
  747.                 pThis->m_siteMap.GetNextAssoc(pos, (void*&)hWnd, (void*&)pSite);
  748.                 ASSERT(pSite->m_pObject != NULL);
  749.                 pSite->m_pObject->AddRef();
  750.                 ppUnk[i++] = pSite->m_pObject;
  751.             }
  752.  
  753.             ASSERT(cObjects == i);
  754.         }
  755.         pEnum = new CEnumUnknown(ppUnk, cObjects);
  756.     }
  757.     CATCH_ALL(e)
  758.     {
  759.         // Note: DELETE_EXCEPTION(e) not necessary
  760.         hr = E_OUTOFMEMORY;
  761.     }
  762.     END_CATCH_ALL
  763.  
  764.     // clean up in case of failure
  765.     if (SUCCEEDED(hr))
  766.     {
  767.         ASSERT(pEnum != NULL);
  768.         *ppEnumUnknown = (IEnumUnknown*)&pEnum->m_xEnumVOID;
  769.     }
  770.     else
  771.     {
  772.         ASSERT(pEnum == NULL);
  773.         ASSERT(*ppEnumUnknown == NULL);
  774.  
  775.         if (ppUnk != NULL)
  776.         {
  777.             for (UINT i = 0; i < cObjects; i++)
  778.             {
  779.                 ASSERT(ppUnk[i] != NULL);
  780.                 ppUnk[i]->Release();
  781.             }
  782.         }
  783.     }
  784.  
  785.     return hr;
  786. }
  787.  
  788. STDMETHODIMP COleControlContainer::XOleContainer::LockContainer(BOOL)
  789. {
  790.     return E_NOTIMPL;
  791. }
  792.