home *** CD-ROM | disk | FTP | other *** search
/ Troubleshooting Netware Systems / CSTRIAL0196.BIN / attach / msj / v10n04 / olecont.exe / CNTLITEM.CPP < prev    next >
C/C++ Source or Header  |  1995-04-01  |  28KB  |  952 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. // CNTLITEM.CPP -- Implementation for the CControlItem class
  3.  
  4.  
  5. #include "stdafx.h"
  6.  
  7. #include "cntlinfo.h"
  8. #include "cntlitem.h"
  9. #include "contdoc.h"
  10. #include "resource.h"
  11.  
  12.  
  13. /////////////////////////////////////////////////////////////////////////////
  14. // Definitions
  15.  
  16. #ifdef _DEBUG
  17. #undef THIS_FILE
  18. static char BASED_CODE THIS_FILE[] = __FILE__;
  19. #endif
  20.  
  21. ///////////////////////////////////////////////////////////////////////////
  22. // struct BINDINFO
  23.  
  24. BINDINFO::~BINDINFO()
  25. {
  26.     delete [] m_lpParamProps;
  27. }
  28.  
  29. ///////////////////////////////////////////////////////////////////////////
  30. // class CControlItem
  31.  
  32. IMPLEMENT_SERIAL(CControlItem, COleClientItem, 0)
  33.  
  34. #define new DEBUG_NEW
  35.  
  36.  
  37. ///////////////////////////////////////////////////////////////////////////
  38. // Constructors & Destructors
  39.  
  40. CControlItem::CControlItem(CContainerDoc* pContainerDoc)
  41.     : COleClientItem(pContainerDoc)
  42. {
  43.     m_pConnPt = NULL;
  44.     m_pEventInfo = NULL;
  45.     m_pCtlDispatch = NULL;
  46.         
  47.     // Setup Last Params Structure
  48.     m_LastParams.cArgs = m_LastParams.cNamedArgs = 0;
  49.     m_LastParams.rgvarg = NULL;
  50.     m_LastParams.rgdispidNamedArgs = NULL;
  51.  
  52.     // Binding members
  53.     m_pConnPtrBind = NULL;
  54.     m_dwBindConnection = 0;
  55.     m_nBinds = 0;
  56.     m_pBindInfo = NULL;
  57. }
  58.  
  59.  
  60. CControlItem::~CControlItem()
  61. {
  62.     if (m_pConnPtrBind != NULL)
  63.     {
  64.         m_pConnPtrBind->Release();
  65.         m_pConnPtrBind = NULL;
  66.     }
  67.  
  68.     if (m_pBindInfo != NULL)
  69.     {
  70.         delete m_pBindInfo;
  71.         m_pBindInfo = NULL;
  72.     }
  73.  
  74.     if (m_pCtlDispatch != NULL)
  75.     {
  76.         m_pCtlDispatch->Release();
  77.         m_pCtlDispatch = NULL;
  78.     }
  79.     
  80.     if (m_LastParams.cArgs > 0)
  81.         CleanUpParams();
  82. }
  83.  
  84.  
  85. ///////////////////////////////////////////////////////////////////////////
  86. // Operations
  87.                               
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CControlItem diagnostics
  90.  
  91. #ifdef _DEBUG
  92. void CControlItem::AssertValid() const
  93. {
  94.     COleClientItem::AssertValid();
  95. }
  96.  
  97. void CControlItem::Dump(CDumpContext& dc) const
  98. {
  99.     COleClientItem::Dump(dc);
  100. }
  101. #endif
  102.  
  103. /////////////////////////////////////////////////////////////////////////////
  104.  
  105.  
  106. ///////////////////////////////////////////////////////////////////////////
  107. // Attributes
  108.                               
  109.  
  110. /////////////////////////////////////////////////////////////////////////////
  111. //  CControlItem interface map
  112.  
  113.  
  114. BEGIN_INTERFACE_MAP(CControlItem, COleClientItem)
  115.     INTERFACE_PART(CControlItem, IID_IDispatch, AmbientProps)
  116.     INTERFACE_PART(CControlItem, IID_IPropertyNotifySink, PropertyNotifySink)
  117. END_INTERFACE_MAP()
  118.  
  119.  
  120. LPUNKNOWN CControlItem::GetInterfaceHook(const void FAR* iid)
  121. {
  122.     //
  123.     //  If requested IID is same as the one we looked up in the registry
  124.     //  (see InitControlInfo), return pointer to our event handler code.
  125.     //
  126.     
  127.     if (*(IID FAR*)iid == m_iidEvents)
  128.         return &m_xEventHandler;
  129.     
  130.     return NULL;
  131. }
  132.                                           
  133.                                    
  134.              
  135. ///////////////////////////////////////////////////////////////////////////
  136. // Overrides
  137.              
  138. BOOL CControlItem::FinishCreate(HRESULT hr)
  139. {
  140.     BOOL bSuper = COleClientItem::FinishCreate(hr);
  141.  
  142.     if (bSuper)
  143.     {
  144.         m_pView = ((CFrameWnd *)(AfxGetApp()->m_pMainWnd))->GetActiveView();
  145.  
  146.         // Note we don't explicitly handle freezing events here, if we wished to,
  147.         // we would grab the OLE object and inform it that its events are frozen.
  148.  
  149.         InitControlInfo();
  150.         InitBindInfo();
  151.  
  152.         //  Wire the control to our event handler
  153.         LPCONNECTIONPOINTCONTAINER lpContainer;
  154.         if (SUCCEEDED(m_lpObject->QueryInterface(
  155.                                 IID_IConnectionPointContainer,
  156.                                 (LPVOID FAR*)&lpContainer)))
  157.         {
  158.             ASSERT(lpContainer != NULL);
  159.             if (SUCCEEDED(lpContainer->FindConnectionPoint(m_iidEvents, &m_pConnPt)))
  160.             {
  161.                 ASSERT(m_pConnPt != NULL);
  162.                 m_pConnPt->Advise(&m_xEventHandler, &m_dwEventConnection);
  163.             }
  164.  
  165.             if (SUCCEEDED(lpContainer->FindConnectionPoint(IID_IPropertyNotifySink, &m_pConnPtrBind)))
  166.             {
  167.                 ASSERT(m_pConnPtrBind != NULL);
  168.                 if (m_pConnPtrBind != NULL) 
  169.                 {
  170.                     m_pConnPtrBind->Advise(&m_xPropertyNotifySink, &m_dwBindConnection);
  171.                 }
  172.             }
  173.  
  174.             lpContainer->Release();
  175.         }
  176.     }
  177.                     
  178.     return bSuper;
  179. }
  180.  
  181. void CControlItem::Release(OLECLOSE dwCloseOption)
  182. {
  183.     UINT nSt = GetItemState ();
  184.     if ((nSt == activeUIState) || (nSt == activeState) || (nSt == openState)) 
  185.         Close (OLECLOSE_NOSAVE);
  186.  
  187.     if (m_pConnPt != NULL)
  188.     {
  189.         m_pConnPt->Unadvise(m_dwEventConnection);
  190.         m_pConnPt->Release();
  191.     }
  192.  
  193.     if (m_pConnPtrBind != NULL)
  194.     {
  195.         m_pConnPtrBind->Unadvise(m_dwBindConnection);
  196.         m_pConnPtrBind->Release();
  197.         m_pConnPtrBind = NULL;
  198.     }
  199.  
  200.     FreeControlInfo();
  201.     COleClientItem::Release(dwCloseOption);
  202. }
  203.              
  204.              
  205.                                    
  206. ///////////////////////////////////////////////////////////////////////////
  207. // Implementation
  208.         
  209. LPUNKNOWN CControlItem::GetCtlInterface(IID iidRequested)
  210. {
  211.     LPUNKNOWN lpUnknown = NULL;
  212.     if (m_lpObject != NULL) 
  213.     { 
  214.         IID iidUnknown = IID_IUnknown;
  215.         if (IsEqualIID(iidRequested, iidUnknown)) 
  216.         {
  217.             lpUnknown = m_lpObject;
  218.             lpUnknown->AddRef();
  219.         } 
  220.         else 
  221.         {
  222.             if (FAILED (m_lpObject->QueryInterface(iidRequested, 
  223.                 (LPVOID *) &lpUnknown))) 
  224.             {
  225.                 lpUnknown = NULL;
  226.             }
  227.         }
  228.     }
  229.     return lpUnknown;
  230. }
  231.         
  232. void CControlItem::InitEventInfo(LPTYPEINFO lpTypeInfo)
  233. {
  234.     LPTYPEATTR lpType = NULL;
  235.     LPFUNCDESC lpFuncDesc = NULL;
  236.  
  237.     if (lpTypeInfo != NULL && SUCCEEDED(lpTypeInfo->GetTypeAttr(&lpType)))
  238.     {
  239.         m_iidEvents = lpType->guid;
  240.         m_nEvents = lpType->cFuncs;
  241.  
  242.         if (m_nEvents > 0)
  243.         {
  244.             TRY
  245.             {
  246.                 m_pEventInfo = new EVENTINFO[m_nEvents];
  247.                         
  248.                 USHORT nCount;
  249.                         
  250.                 //
  251.                 //  Enumerate events, getting their member id's and names
  252.                 //
  253.                 
  254.                 for (nCount = 0; nCount < m_nEvents; nCount++)
  255.                 {
  256.                     m_pEventInfo[nCount].memid = -1;
  257.                     m_pEventInfo[nCount].cParams = 0;
  258.                     m_pEventInfo[nCount].pbstr = NULL;
  259.     
  260.                     if (SUCCEEDED(lpTypeInfo->GetFuncDesc(nCount, &lpFuncDesc)))
  261.                     {
  262.                         m_pEventInfo[nCount].memid = lpFuncDesc->memid;
  263.                         m_pEventInfo[nCount].cParams = lpFuncDesc->cParams;
  264.     
  265.                         m_pEventInfo[nCount].pbstr = new BSTR[lpFuncDesc->cParams+1];
  266.                         UINT cNames;
  267.                         lpTypeInfo->GetNames(lpFuncDesc->memid, m_pEventInfo[nCount].pbstr, 
  268.                                 lpFuncDesc->cParams+1, &cNames);
  269.                                         
  270.                         ASSERT((unsigned)lpFuncDesc->cParams+1 == cNames);
  271.                         lpTypeInfo->ReleaseFuncDesc(lpFuncDesc);
  272.                         lpFuncDesc = NULL;
  273.                     }
  274.                 }
  275.             }
  276.             CATCH(CMemoryException, e)
  277.             {
  278.                 if (lpType != NULL)
  279.                     lpTypeInfo->ReleaseTypeAttr(lpType);
  280.  
  281.                 if (lpFuncDesc != NULL)
  282.                         lpTypeInfo->ReleaseFuncDesc(lpFuncDesc);
  283.                                             
  284.                 lpType = NULL;
  285.                 lpFuncDesc = NULL;
  286.             }
  287.             END_CATCH                
  288.         }
  289.         lpTypeInfo->ReleaseTypeAttr(lpType);
  290.         lpType = NULL;
  291.     }
  292. }
  293.  
  294.  
  295. void CControlItem::InitBindInfo()
  296. {
  297.     LPTYPEINFO lpTypeInfo = NULL;
  298.     LPTYPEATTR lpType = NULL;
  299.     LPVARDESC lpVarDesc = NULL;
  300.  
  301.     TRY
  302.     {
  303.         m_pBindInfo = new BINDINFO;
  304.         ASSERT(m_pBindInfo != NULL);
  305.         m_pCtlDispatch = (LPDISPATCH) GetCtlInterface(IID_IDispatch);
  306.  
  307.         if (m_pCtlDispatch != NULL) 
  308.         {
  309.             UINT nTypeCount = 0;
  310.             if ((SUCCEEDED(m_pCtlDispatch->GetTypeInfoCount(&nTypeCount))) && (nTypeCount == 1)) 
  311.             {
  312.                 if (SUCCEEDED(m_pCtlDispatch->GetTypeInfo(0, GetUserDefaultLCID(), &lpTypeInfo))) 
  313.                  {
  314.                     if (SUCCEEDED(lpTypeInfo->GetTypeAttr(&lpType))) 
  315.                     {
  316.                         if ((m_pBindInfo->m_nParamCount = lpType->cVars) != 0) 
  317.                         {
  318.                             m_pBindInfo->m_lpParamProps = new PARAMPROPINFO [m_pBindInfo->m_nParamCount];
  319.                             ASSERT(m_pBindInfo->m_lpParamProps != NULL);
  320.                             UINT nDesc = 0;
  321.                             UINT nParam = 0;
  322.                             while (nParam < m_pBindInfo->m_nParamCount) 
  323.                             {
  324.                                 lpTypeInfo->GetVarDesc(nDesc++, &lpVarDesc);
  325.                                 ASSERT(lpVarDesc != NULL);
  326.                                 if (lpVarDesc->varkind == VAR_DISPATCH) 
  327.                                 {
  328.                                     LPPARAMPROPINFO lpParam = &m_pBindInfo->m_lpParamProps[nParam];
  329.                                     lpParam->id = lpVarDesc->memid;
  330.                                     BSTR bstr = NULL;
  331.                                     UINT nNameCount;
  332.                                     lpTypeInfo->GetNames(lpParam->id, &bstr, 1, &nNameCount);
  333.                                     ASSERT (nNameCount == 1);
  334.                                     if (nNameCount > 0) 
  335.                                     {
  336.                                         char sz[80];
  337.                                         
  338.                                            wcstombs(sz,
  339.                                             (const unsigned short*) bstr, 80);
  340.                                            lpParam->strName = sz;
  341.                                     }
  342.                                     ::SysFreeString(bstr);
  343.                                     bstr = NULL;
  344.                                     nParam++;
  345.                                 } 
  346.                                 else 
  347.                                 {
  348.                                     m_pBindInfo->m_nParamCount--;
  349.                                 }
  350.                                 lpTypeInfo->ReleaseVarDesc(lpVarDesc);
  351.                                 lpVarDesc = NULL;
  352.                             }
  353.                         }
  354.                         lpTypeInfo->ReleaseTypeAttr(lpType);
  355.                         lpType = NULL;
  356.                     }
  357.                     lpTypeInfo->Release();
  358.                     lpTypeInfo = NULL;
  359.                 }
  360.                 m_pCtlDispatch->Release();
  361.                 m_pCtlDispatch = NULL;
  362.             } 
  363.             else 
  364.             {
  365.                 TRACE(_T("Controls primary IDispatch could not be found!\n"));
  366.                 AfxThrowMemoryException(); // force cleanup
  367.             }
  368.         }
  369.     }
  370.     CATCH(CMemoryException, e)
  371.     {
  372.         if (m_pCtlDispatch != NULL)
  373.         {
  374.             m_pCtlDispatch->Release();
  375.             m_pCtlDispatch = NULL;
  376.         }
  377.  
  378.         if (lpTypeInfo != NULL)
  379.         {
  380.             if (lpType != NULL)
  381.                 lpTypeInfo->ReleaseTypeAttr(lpType);
  382.  
  383.             if (lpVarDesc != NULL)
  384.                 lpTypeInfo->ReleaseVarDesc(lpVarDesc);
  385.  
  386.             lpTypeInfo->Release();
  387.         }
  388.  
  389.         lpTypeInfo = NULL;
  390.         lpType = NULL;
  391.         lpVarDesc = NULL;
  392.     }
  393.     END_CATCH
  394. }
  395.  
  396. void CControlItem::InitControlInfo()
  397. {
  398.     //
  399.     //  Use the control's class info to obtain information about
  400.     //  its events, etc.
  401.     //
  402.     
  403.     ASSERT_VALID(this);
  404.     ASSERT(m_lpObject != NULL);
  405.     
  406.     LPPROVIDECLASSINFO lpProvide = NULL;
  407.             
  408.     if (SUCCEEDED(m_lpObject->QueryInterface(
  409.                 IID_IProvideClassInfo,
  410.                 (LPVOID FAR*)&lpProvide)))
  411.     {
  412.         ASSERT(lpProvide != NULL);
  413.                 
  414.         LPTYPEINFO lpClassInfo = NULL;
  415.  
  416.         if (SUCCEEDED(lpProvide->GetClassInfo(&lpClassInfo)))
  417.         {
  418.             ASSERT(lpClassInfo != NULL);
  419.  
  420.             LPTYPEATTR lpType;
  421.             if (SUCCEEDED(lpClassInfo->GetTypeAttr(&lpType)))
  422.             {
  423.                 ASSERT(lpType != NULL);
  424.                 ASSERT(lpType->typekind == TKIND_COCLASS);
  425.                 
  426.                 UINT nCount;
  427.                 int iFlags;
  428.                 HREFTYPE hRefType;
  429.                 
  430.                 //
  431.                 //  Search for typeinfo of the default events interface.
  432.                 //
  433.     
  434.                 for (nCount = 0; nCount < lpType->cImplTypes; nCount++)
  435.                 {
  436.                     if (SUCCEEDED(lpClassInfo->GetImplTypeFlags(nCount, &iFlags)) &&
  437.                         ((iFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE))
  438.                     {
  439.                         LPTYPEINFO lpTypeInfo = NULL;
  440.                         
  441.                         if (SUCCEEDED(lpClassInfo->GetRefTypeOfImplType(nCount, &hRefType)) &&
  442.                             SUCCEEDED(lpClassInfo->GetRefTypeInfo(hRefType, &lpTypeInfo)))
  443.                         {
  444.                             //
  445.                             //  Found it!  Use it to initialize event table.
  446.                             //
  447.  
  448.                             ASSERT(lpTypeInfo != NULL);
  449.                             InitEventInfo(lpTypeInfo);                           
  450.                             lpTypeInfo->Release();
  451.                             lpTypeInfo = NULL;
  452.                         }
  453.                         
  454.                         break;
  455.                     }
  456.                 }
  457.             
  458.                 lpClassInfo->ReleaseTypeAttr(lpType);
  459.                 lpType = NULL;
  460.             }
  461.                             
  462.             lpClassInfo->Release();
  463.             lpClassInfo = NULL;
  464.         }
  465.             
  466.         lpProvide->Release();
  467.     }
  468. }
  469.  
  470.  
  471. void CControlItem::FreeControlInfo(void)
  472. {
  473.     if (m_pEventInfo != NULL)
  474.     {
  475.         USHORT i;
  476.     
  477.         for (i = 0; i < m_nEvents; i++)
  478.             if (m_pEventInfo[i].pbstr != NULL)
  479.             {
  480.                 SHORT j;
  481.                 for (j = 0; j < m_pEventInfo[i].cParams+1; j++)
  482.                     ::SysFreeString(m_pEventInfo[i].pbstr[j]);
  483.                 delete [] m_pEventInfo[i].pbstr;
  484.             }
  485.         delete [] m_pEventInfo;
  486.         m_pEventInfo = NULL;
  487.     }                            
  488. }
  489.  
  490. PARAMPROPINFO* CControlItem::GetParamPropInfo(DISPID id)
  491. {
  492.     USHORT i;
  493.  
  494.     for (i = 0; i < m_pBindInfo->m_nParamCount; i++)
  495.         if (id == m_pBindInfo->m_lpParamProps[i].id)
  496.             return &(m_pBindInfo->m_lpParamProps[i]);
  497.  
  498.     return NULL;
  499. }
  500.  
  501. EVENTINFO* CControlItem::GetEventInfo(MEMBERID memid)
  502. {
  503.     USHORT i;
  504.  
  505.     for (i = 0; i < m_nEvents; i++)
  506.         if (memid == m_pEventInfo[i].memid)
  507.             return &m_pEventInfo[i];
  508.         
  509.     return NULL;
  510. }
  511.                                    
  512.         
  513. void CControlItem::CleanUpParams()
  514. {              
  515.     ASSERT_VALID(this);          
  516.     
  517.     DISPPARAMS FAR* lpDispparams = &m_LastParams;
  518.           
  519.     if (lpDispparams->rgvarg != NULL)          
  520.     {
  521.         for (UINT i=0; i<lpDispparams->cArgs; i++)
  522.         {
  523.             switch(lpDispparams->rgvarg[i].vt)
  524.             {
  525.                 case VT_BSTR:
  526.                     ::SysFreeString(lpDispparams->rgvarg[i].bstrVal);
  527.                     break;
  528.                 case VT_DISPATCH:
  529.                     lpDispparams->rgvarg[i].pdispVal->Release();
  530.                     break;
  531.                 case VT_UNKNOWN:
  532.                     lpDispparams->rgvarg[i].punkVal->Release();
  533.                     break;
  534.                 default:
  535.                     break;
  536.             }
  537.         }
  538.         delete lpDispparams->rgvarg;
  539.     }
  540.  
  541.     lpDispparams->rgvarg = NULL;
  542.     
  543.     if (lpDispparams->rgdispidNamedArgs != NULL)
  544.         delete lpDispparams->rgdispidNamedArgs;
  545.     lpDispparams->rgdispidNamedArgs = NULL;
  546. }        
  547.                                  
  548. void CControlItem::CopyParams(DISPPARAMS FAR* lpDispparams)
  549. {       
  550.     UINT i;             
  551.  
  552.     if (lpDispparams == NULL)
  553.         return;                    // can't copy bogus params
  554.         
  555.     if (m_LastParams.cArgs > 0)
  556.         CleanUpParams();
  557.  
  558.     // Change state information about incoming                           
  559.     m_LastParams.cArgs = lpDispparams->cArgs;    
  560.     if (lpDispparams->cArgs == 0)
  561.         m_LastParams.rgvarg = NULL;
  562.     else
  563.         m_LastParams.rgvarg = new VARIANTARG[lpDispparams->cArgs];
  564.     
  565.     m_LastParams.cNamedArgs = lpDispparams->cNamedArgs;
  566.     if(lpDispparams->cNamedArgs == 0)
  567.           m_LastParams.rgdispidNamedArgs = NULL;
  568.     else
  569.     {
  570.           m_LastParams.rgdispidNamedArgs = new DISPID[lpDispparams->cNamedArgs];
  571.               
  572.         for(i = 0; i < m_LastParams.cNamedArgs; ++i)
  573.             m_LastParams.rgdispidNamedArgs[i] = lpDispparams->rgdispidNamedArgs[i];
  574.     }
  575.     
  576.     for (i = 0; i < m_LastParams.cArgs; i++)
  577.     {               
  578.         // Copy Parameter type
  579.         m_LastParams.rgvarg[i].vt = lpDispparams->rgvarg[i].vt;
  580.  
  581.         switch(lpDispparams->rgvarg[i].vt)
  582.         {       
  583.             case VT_I2:
  584.                 m_LastParams.rgvarg[i].iVal = lpDispparams->rgvarg[i].iVal;
  585.                 break;
  586.      
  587.             case VT_I4:
  588.                 m_LastParams.rgvarg[i].lVal = lpDispparams->rgvarg[i].lVal;
  589.                 break;
  590.      
  591.             case VT_R4:
  592.                 m_LastParams.rgvarg[i].fltVal = lpDispparams->rgvarg[i].fltVal;
  593.                 break;
  594.      
  595.             case VT_R8:
  596.                 m_LastParams.rgvarg[i].dblVal = lpDispparams->rgvarg[i].dblVal;
  597.                 break;
  598.  
  599.             case VT_BOOL:
  600.                 m_LastParams.rgvarg[i].bool = lpDispparams->rgvarg[i].bool;
  601.                 break;
  602.                                                                           
  603.             case VT_ERROR:
  604.                 m_LastParams.rgvarg[i].scode = lpDispparams->rgvarg[i].scode;
  605.                 break;
  606.                                                                             
  607.             case VT_CY:
  608.                 m_LastParams.rgvarg[i].cyVal = lpDispparams->rgvarg[i].cyVal;
  609.                 break;
  610.  
  611.             case VT_DATE:
  612.                 m_LastParams.rgvarg[i].date = lpDispparams->rgvarg[i].date;
  613.                 break;
  614.                 
  615.             case VT_BSTR:
  616.                 m_LastParams.rgvarg[i].bstrVal = ::SysAllocString(lpDispparams->rgvarg[i].bstrVal);
  617.                 break;
  618.                                                                              
  619.             case VT_UNKNOWN:
  620.                 m_LastParams.rgvarg[i].punkVal = lpDispparams->rgvarg[i].punkVal;
  621.                 break;
  622.                                                                                 
  623.             case VT_DISPATCH:
  624.                 m_LastParams.rgvarg[i].pdispVal = lpDispparams->rgvarg[i].pdispVal;
  625.                 break;
  626.                 
  627.             case (VT_I2 | VT_BYREF):
  628.                 m_LastParams.rgvarg[i].piVal = lpDispparams->rgvarg[i].piVal;
  629.                 break;
  630.                 
  631.             case (VT_I4 | VT_BYREF):
  632.                 m_LastParams.rgvarg[i].plVal = lpDispparams->rgvarg[i].plVal;
  633.                 break;
  634.                 
  635.             case (VT_R4 | VT_BYREF):
  636.                 m_LastParams.rgvarg[i].pfltVal = lpDispparams->rgvarg[i].pfltVal;
  637.                 break;
  638.  
  639.             case (VT_R8 | VT_BYREF):
  640.                 m_LastParams.rgvarg[i].pdblVal = lpDispparams->rgvarg[i].pdblVal;
  641.                 break;
  642.  
  643.             case (VT_BOOL | VT_BYREF):
  644.                 m_LastParams.rgvarg[i].pbool = lpDispparams->rgvarg[i].pbool;
  645.                 break;
  646.                                                                           
  647.             case (VT_ERROR | VT_BYREF):
  648.                 m_LastParams.rgvarg[i].pscode = lpDispparams->rgvarg[i].pscode;
  649.                 break;
  650.                                                                             
  651.             case (VT_CY | VT_BYREF):
  652.                 m_LastParams.rgvarg[i].pcyVal = lpDispparams->rgvarg[i].pcyVal;
  653.                 break;
  654.  
  655.             case (VT_DATE | VT_BYREF):
  656.                 m_LastParams.rgvarg[i].pdate = lpDispparams->rgvarg[i].pdate;
  657.                 break;
  658.                 
  659.             case (VT_BSTR | VT_BYREF):
  660.                 m_LastParams.rgvarg[i].pbstrVal = lpDispparams->rgvarg[i].pbstrVal;
  661.                 break;
  662.                              
  663.             case (VT_VARIANT | VT_BYREF):
  664.                 m_LastParams.rgvarg[i].pvarVal = lpDispparams->rgvarg[i].pvarVal;
  665.                 break;
  666.                                                                                              
  667.             case (VT_UNKNOWN | VT_BYREF):
  668.                 m_LastParams.rgvarg[i].ppunkVal = lpDispparams->rgvarg[i].ppunkVal;
  669.                 break;
  670.                                                                                 
  671.             case (VT_DISPATCH | VT_BYREF):
  672.                 m_LastParams.rgvarg[i].ppdispVal = lpDispparams->rgvarg[i].ppdispVal;
  673.                 break;
  674.                 
  675.             default:
  676.                 break;
  677.         }
  678.     }
  679. }
  680.                                           
  681. /////////////////////////////////////////////////////////////////////////////
  682. //  Callbacks
  683.  
  684. void CControlItem::OnEvent(DISPID dispID, DISPPARAMS FAR* lpDispparams)
  685. {
  686.     // Just set the dispid and dispparams pointers to the latest information
  687.  
  688.     m_EventID = dispID;
  689.     CopyParams(lpDispparams);
  690.  
  691.     // find the event
  692.  
  693.     EVENTINFO* pEvent = GetEventInfo(m_EventID);
  694.     if (pEvent == NULL)
  695.     { 
  696.           TRACE1("Unknown event ID: %u\n", m_EventID);
  697.         return;
  698.     }
  699.  
  700.     CString strMsg;
  701.     char sz[80];
  702.     unsigned nParameter;
  703.  
  704.     wcstombs(sz,
  705.             (const unsigned short*) pEvent->pbstr[0], ELEMENTS(sz));
  706.     strMsg.Format(_T("%s("), sz);
  707.  
  708.     for (nParameter = 1; nParameter <= m_LastParams.cArgs;
  709.         nParameter++)
  710.     {
  711.         wcstombs(sz, (const unsigned short*)
  712.             pEvent->pbstr[nParameter], ELEMENTS(sz));
  713.  
  714.         if (nParameter > 1)
  715.             strMsg += _T(", ");
  716.         strMsg += sz;
  717.         strMsg += _T("= ");
  718.     }
  719.  
  720.     strMsg += _T(")");
  721.     TRACE(strMsg);
  722.     TRACE(_T("\n"));
  723.     m_pView->MessageBox(strMsg, _T("CControlItem::OnEvent"), MB_OK);
  724. }
  725.  
  726. HRESULT CControlItem::OnPropertyNotification(DISPID dispID, UINT idsOccurence)
  727. {
  728.     CString strMsg;
  729.     PARAMPROPINFO* pInfo = GetParamPropInfo(dispID);
  730.  
  731.     if (pInfo == NULL)
  732.     {
  733.         strMsg.Format(_T("%s: Unknown DISPID = %d"),
  734.             (idsOccurence == IDS_BOUNDPROP_REQEDIT) ? _T("Edit Request") : _T("Change Notify"),
  735.             dispID);
  736.     }
  737.     else
  738.     {
  739.         strMsg.Format(_T("%s: %s"),
  740.             (idsOccurence == IDS_BOUNDPROP_REQEDIT) ? _T("Edit Request") : _T("Change Notify"),
  741.             pInfo->strName);
  742.     }
  743.  
  744.     TRACE(strMsg);
  745.     TRACE(_T("\n"));
  746.     m_pView->MessageBox(strMsg,
  747.         _T("CControlItem::OnPropertyNotifcation()"), MB_OK);
  748.     return NOERROR;
  749. }
  750.  
  751.  
  752. /////////////////////////////////////////////////////////////////////////////
  753. //  CControlItem::XEventHandler
  754.  
  755.  
  756. STDMETHODIMP_(ULONG) CControlItem::XEventHandler::AddRef()
  757. {
  758.     METHOD_PROLOGUE(CControlItem, EventHandler)
  759.     return (ULONG)pThis->ExternalAddRef();
  760. }
  761.  
  762.  
  763. STDMETHODIMP_(ULONG) CControlItem::XEventHandler::Release()
  764. {
  765.     METHOD_PROLOGUE(CControlItem, EventHandler)
  766.     return (ULONG)pThis->ExternalRelease();
  767. }
  768.  
  769.  
  770. STDMETHODIMP CControlItem::XEventHandler::QueryInterface(
  771.     REFIID iid, LPVOID far* ppvObj)
  772. {
  773.     METHOD_PROLOGUE(CControlItem, EventHandler)
  774.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  775. }
  776.  
  777.  
  778. STDMETHODIMP CControlItem::XEventHandler::GetTypeInfoCount(unsigned int FAR* pctinfo)
  779. {
  780.     METHOD_PROLOGUE(CControlItem, EventHandler)
  781.     ASSERT_VALID(pThis);
  782.  
  783.     *pctinfo = 0;
  784.     return NOERROR;
  785. }
  786.  
  787.  
  788. STDMETHODIMP CControlItem::XEventHandler::GetTypeInfo(unsigned int itinfo,
  789.       LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  790. {
  791.     METHOD_PROLOGUE(CControlItem, EventHandler)
  792.     ASSERT_VALID(pThis);
  793.  
  794.     return ResultFromScode(E_NOTIMPL);
  795. }
  796.  
  797.  
  798. STDMETHODIMP CControlItem::XEventHandler::GetIDsOfNames(REFIID riid,
  799.       LPTSTR FAR* rgszNames, unsigned int cNames, LCID lcid,
  800.       DISPID FAR* rgdispid)
  801. {
  802.     METHOD_PROLOGUE(CControlItem, EventHandler)
  803.     ASSERT_VALID(pThis);
  804.  
  805.     return ResultFromScode(E_NOTIMPL);
  806. }
  807.  
  808.  
  809. STDMETHODIMP CControlItem::XEventHandler::Invoke(DISPID dispidMember,
  810.       REFIID riid, LCID lcid, unsigned short wFlags, DISPPARAMS FAR* lpDispparams,
  811.       VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, 
  812.       unsigned int FAR* puArgErr)
  813. {
  814.     METHOD_PROLOGUE(CControlItem, EventHandler)
  815.     ASSERT_VALID(pThis);
  816.  
  817.     pThis->OnEvent(dispidMember, lpDispparams);    // Call the event handler, who also cleans up.
  818.     
  819.     return NOERROR;
  820. }
  821.                                           
  822.  
  823. /////////////////////////////////////////////////////////////////////////////
  824. //  CControlItem::XPropertyNotifySink
  825.  
  826. STDMETHODIMP_(ULONG) CControlItem::XPropertyNotifySink::AddRef()
  827. {
  828.     METHOD_PROLOGUE(CControlItem, PropertyNotifySink)
  829.     return (ULONG)pThis->ExternalAddRef();
  830. }
  831.  
  832.  
  833. STDMETHODIMP_(ULONG) CControlItem::XPropertyNotifySink::Release()
  834. {
  835.     METHOD_PROLOGUE(CControlItem, PropertyNotifySink)
  836.     return (ULONG)pThis->ExternalRelease();
  837. }
  838.  
  839.  
  840. STDMETHODIMP CControlItem::XPropertyNotifySink::QueryInterface(
  841.     REFIID iid, LPVOID far* ppvObj)
  842. {
  843.     METHOD_PROLOGUE(CControlItem, PropertyNotifySink)
  844.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  845. }
  846.  
  847. STDMETHODIMP CControlItem::XPropertyNotifySink::OnChanged(
  848.       DISPID dispid)
  849. {
  850.     METHOD_PROLOGUE(CControlItem, PropertyNotifySink)
  851.     return (pThis->OnPropertyNotification(dispid, IDS_BOUNDPROP_CHANGED));
  852. }
  853.  
  854.  
  855. STDMETHODIMP CControlItem::XPropertyNotifySink::OnRequestEdit(
  856.       DISPID dispid)
  857. {
  858.     METHOD_PROLOGUE(CControlItem, PropertyNotifySink)
  859.     return (pThis->OnPropertyNotification(dispid, IDS_BOUNDPROP_REQEDIT));
  860. }
  861.  
  862.  
  863. /////////////////////////////////////////////////////////////////////////////
  864. //  CControlItem::XAmbientProps
  865.  
  866.  
  867. STDMETHODIMP_(ULONG) CControlItem::XAmbientProps::AddRef()
  868. {
  869.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  870.     return (ULONG)pThis->ExternalAddRef();
  871. }
  872.  
  873.  
  874. STDMETHODIMP_(ULONG) CControlItem::XAmbientProps::Release()
  875. {
  876.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  877.     return (ULONG)pThis->ExternalRelease();
  878. }
  879.  
  880.  
  881. STDMETHODIMP CControlItem::XAmbientProps::QueryInterface(
  882.     REFIID iid, LPVOID far* ppvObj)
  883. {
  884.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  885.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  886. }
  887.  
  888.  
  889. STDMETHODIMP CControlItem::XAmbientProps::GetTypeInfoCount(unsigned int FAR* pctinfo)
  890. {
  891.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  892.     ASSERT_VALID(pThis);
  893.     *pctinfo = 0;
  894.     return NOERROR;
  895. }
  896.  
  897.  
  898. STDMETHODIMP CControlItem::XAmbientProps::GetTypeInfo(unsigned int itinfo,
  899.       LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  900. {
  901.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  902.     ASSERT_VALID(pThis);
  903.     return ResultFromScode(E_NOTIMPL);
  904. }
  905.  
  906.  
  907. STDMETHODIMP CControlItem::XAmbientProps::GetIDsOfNames(REFIID riid,
  908.       LPTSTR FAR* rgszNames, unsigned int cNames, LCID lcid,
  909.       DISPID FAR* rgdispid)
  910. {
  911.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  912.     ASSERT_VALID(pThis);
  913.  
  914.     UINT nIdx = 0;
  915.     CContainerDoc* pDoc = (CContainerDoc*)pThis->m_pDocument;
  916.  
  917.     while (nIdx < cNames) 
  918.     {
  919.         LPAPROP lpAprop = pDoc->FindAprop(rgszNames[nIdx]);
  920.         if (lpAprop)
  921.         {
  922.             rgdispid[nIdx] = lpAprop->dispid;
  923.         } 
  924.         else 
  925.         {
  926.             rgdispid[nIdx] = DISPID_UNKNOWN;
  927.         }
  928.         nIdx++;
  929.     }
  930.     return NOERROR;
  931. }
  932.  
  933.  
  934. STDMETHODIMP CControlItem::XAmbientProps::Invoke(DISPID dispidMember, REFIID riid,
  935.       LCID lcid, unsigned short wFlags, DISPPARAMS FAR* lpDispparams, 
  936.       VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, unsigned int FAR* puArgErr)
  937. {
  938.     METHOD_PROLOGUE(CControlItem, AmbientProps)
  939.     ASSERT_VALID(pThis);
  940.  
  941.     HRESULT hr = ResultFromScode (DISP_E_MEMBERNOTFOUND);
  942.  
  943.     CContainerDoc* pDoc = (CContainerDoc*)pThis->m_pDocument;
  944.     LPAPROP lpAprop = pDoc->FindAprop(dispidMember);
  945.     if (lpAprop) 
  946.     {
  947.         TFVarCopy(pvarResult, &lpAprop->varValue);
  948.         hr = NOERROR;
  949.     }
  950.     return (hr);
  951. }
  952.