home *** CD-ROM | disk | FTP | other *** search
/ The Best of Select: Windows 95 Special 1 / WINDOWS95_1.bin / internet / vogon / cntritem.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-24  |  28.9 KB  |  923 lines

  1. // cntritem.cpp : implementation of the CVogonCntrItem class
  2. //
  3.  
  4. #include "StdAfx.h"
  5.  
  6. #include "Vogon.h"
  7.  
  8. #include "CntrInfo.h"
  9. #include "CntrItem.h"
  10. #include "VogonDoc.h"
  11. #include "VogonVw.h"
  12.  
  13. #ifdef _DEBUG
  14. #undef THIS_FILE
  15. static char BASED_CODE THIS_FILE[] = __FILE__;
  16. #endif
  17.  
  18. /////////////////////////////////////////////////////////////////////////////
  19. // CVogonCntrItem implementation
  20.  
  21. IMPLEMENT_SERIAL(CVogonCntrItem, COleClientItem, 0)
  22.  
  23. CVogonCntrItem::CVogonCntrItem(CVogonDoc* pContainer) : COleClientItem(pContainer)
  24. {
  25.    m_pConnPt = NULL;
  26.    m_pEventInfo = NULL;
  27.  
  28.    // Setup Last Params Structure
  29.    m_LastParams.cArgs = m_LastParams.cNamedArgs = 0;
  30.    m_LastParams.rgvarg = NULL;
  31.    m_LastParams.rgdispidNamedArgs = NULL;
  32. }
  33.  
  34. CVogonCntrItem::~CVogonCntrItem()
  35. {
  36.    if (m_LastParams.cArgs > 0)
  37.    {
  38.       CleanUpParams();
  39.    }
  40. }
  41.  
  42.  
  43. /////////////////////////////////////////////////////////////////////////////
  44. //  CVogonCntrItem interface map
  45.  
  46. BEGIN_INTERFACE_MAP(CVogonCntrItem, COleClientItem)
  47.     // INTERFACE_PART(CVogonCntrItem, IID_IDispatch, AmbientProps)
  48.     // INTERFACE_PART(CVogonCntrItem, IID_IPropertyNotifySink, PropertyNotifySink)
  49. END_INTERFACE_MAP()
  50.  
  51.  
  52. /////////////////////////////////////////////////////////////////////////////
  53. // CVogonCntrItem implementation
  54. LPUNKNOWN CVogonCntrItem::GetInterfaceHook(const void FAR* iid)
  55. {
  56.    //
  57.    //  If requested IID is same as the one we looked up in the registry
  58.    //  (see InitControlInfo), return pointer to our event handler code.
  59.    //
  60.  
  61.    if (*(IID FAR*)iid == m_iidEvents)
  62.    {
  63.       return &m_xEventHandler;
  64.    }
  65.  
  66.    return NULL;
  67. }
  68.  
  69. ///////////////////////////////////////////////////////////////////////////
  70. // Overrides
  71.              
  72. /////////////////////////////////////////////////////////////////////////////
  73. //
  74. BOOL CVogonCntrItem::FinishCreate(HRESULT hr)
  75. {
  76.    BOOL status = COleClientItem::FinishCreate(hr);
  77.  
  78.    if (status)
  79.    {
  80.       InitControlInfo();
  81.  
  82.       //  Wire the control to our event handler
  83.       LPCONNECTIONPOINTCONTAINER lpContainer;
  84.       // Get a pointer to the interface
  85.       if (SUCCEEDED(m_lpObject->QueryInterface(IID_IConnectionPointContainer,
  86.                                                (LPVOID FAR*)&lpContainer)))
  87.       {
  88.          ASSERT(lpContainer != NULL);
  89.          // Get a pointer to the connection point
  90.          if (SUCCEEDED(lpContainer->FindConnectionPoint(m_iidEvents, &m_pConnPt)))
  91.          {  // Tell the connection point about our event handler
  92.             ASSERT(m_pConnPt != NULL);
  93.             m_pConnPt->Advise(&m_xEventHandler, &m_dwEventConnection);
  94.          }
  95.          // We are done with the interface, let it go
  96.          lpContainer->Release();
  97.       }
  98.    }
  99.               
  100.    return status;
  101. }
  102.  
  103. /////////////////////////////////////////////////////////////////////////////
  104. //
  105. void CVogonCntrItem::Release(OLECLOSE dwCloseOption)
  106. {
  107.     UINT nSt = GetItemState ();
  108.     if ((nSt == activeUIState) || (nSt == activeState) || (nSt == openState)) 
  109.         Close (OLECLOSE_NOSAVE);
  110.  
  111.     if (m_pConnPt != NULL)
  112.     {
  113.         m_pConnPt->Unadvise(m_dwEventConnection);
  114.         m_pConnPt->Release();
  115.     }
  116.  
  117.     FreeControlInfo();
  118.     COleClientItem::Release(dwCloseOption);
  119. }
  120.              
  121.              
  122.                                    
  123. ///////////////////////////////////////////////////////////////////////////
  124. // Implementation
  125.         
  126. LPUNKNOWN CVogonCntrItem::GetCtlInterface(IID iidRequested)
  127. {
  128.    LPUNKNOWN lpUnknown = NULL;
  129.    if (m_lpObject != NULL) 
  130.    { 
  131.       IID iidUnknown = IID_IUnknown;
  132.       if (IsEqualIID(iidRequested, iidUnknown)) 
  133.       {
  134.          lpUnknown = m_lpObject;
  135.          lpUnknown->AddRef();
  136.       } 
  137.       else 
  138.       {
  139.          if (FAILED (m_lpObject->QueryInterface(iidRequested, (LPVOID *) &lpUnknown))) 
  140.          {
  141.             lpUnknown = NULL;
  142.          }
  143.       }
  144.    }
  145.    return lpUnknown;
  146. }
  147.         
  148. /////////////////////////////////////////////////////////////////////////////
  149. //
  150. void CVogonCntrItem::InitEventInfo(LPTYPEINFO lpTypeInfo)
  151. {
  152.     LPTYPEATTR lpType = NULL;
  153.     LPFUNCDESC lpFuncDesc = NULL;
  154.  
  155.     if (lpTypeInfo != NULL && SUCCEEDED(lpTypeInfo->GetTypeAttr(&lpType)))
  156.     {
  157.         m_iidEvents = lpType->guid;
  158.         m_nEvents = lpType->cFuncs;
  159.  
  160.         if (m_nEvents > 0)
  161.         {
  162.             TRY
  163.             {
  164.                 m_pEventInfo = new EVENTINFO[m_nEvents];
  165.                         
  166.                 USHORT nCount;
  167.                         
  168.                 //
  169.                 //  Enumerate events, getting their member id's and names
  170.                 //
  171.                 
  172.                 for (nCount = 0; nCount < m_nEvents; nCount++)
  173.                 {
  174.                     m_pEventInfo[nCount].memid = -1;
  175.                     m_pEventInfo[nCount].cParams = 0;
  176.                     m_pEventInfo[nCount].pbstr = NULL;
  177.     
  178.                     if (SUCCEEDED(lpTypeInfo->GetFuncDesc(nCount, &lpFuncDesc)))
  179.                     {
  180.                         m_pEventInfo[nCount].memid = lpFuncDesc->memid;
  181.                         m_pEventInfo[nCount].cParams = lpFuncDesc->cParams;
  182.     
  183.                         m_pEventInfo[nCount].pbstr = new BSTR[lpFuncDesc->cParams+1];
  184.                         UINT cNames;
  185.                         lpTypeInfo->GetNames(lpFuncDesc->memid, m_pEventInfo[nCount].pbstr, 
  186.                                 lpFuncDesc->cParams+1, &cNames);
  187.                                         
  188.                         ASSERT((unsigned)lpFuncDesc->cParams+1 == cNames);
  189.                         lpTypeInfo->ReleaseFuncDesc(lpFuncDesc);
  190.                         lpFuncDesc = NULL;
  191.                     }
  192.                 }
  193.             }
  194.             CATCH(CMemoryException, e)
  195.             {
  196.                 if (lpType != NULL)
  197.                     lpTypeInfo->ReleaseTypeAttr(lpType);
  198.  
  199.                 if (lpFuncDesc != NULL)
  200.                         lpTypeInfo->ReleaseFuncDesc(lpFuncDesc);
  201.                                             
  202.                 lpType = NULL;
  203.                 lpFuncDesc = NULL;
  204.             }
  205.             END_CATCH                
  206.         }
  207.         lpTypeInfo->ReleaseTypeAttr(lpType);
  208.         lpType = NULL;
  209.     }
  210. }
  211.  
  212. /////////////////////////////////////////////////////////////////////////////
  213. //
  214. void CVogonCntrItem::InitControlInfo()
  215. {
  216.    //
  217.    //  Use the control's class info to obtain information about
  218.    //  its events, etc.
  219.    //
  220.  
  221.    ASSERT_VALID(this);
  222.    ASSERT(m_lpObject != NULL);
  223.  
  224.    LPPROVIDECLASSINFO lpProvide = NULL;
  225.       
  226.    if (SUCCEEDED(m_lpObject->QueryInterface(IID_IProvideClassInfo, (LPVOID FAR*)&lpProvide)))
  227.    {
  228.       ASSERT(lpProvide != NULL);
  229.     
  230.       LPTYPEINFO lpClassInfo = NULL;
  231.  
  232.       if (SUCCEEDED(lpProvide->GetClassInfo(&lpClassInfo)))
  233.       {
  234.          ASSERT(lpClassInfo != NULL);
  235.  
  236.          LPTYPEATTR lpType;
  237.          if (SUCCEEDED(lpClassInfo->GetTypeAttr(&lpType)))
  238.          {
  239.             ASSERT(lpType != NULL);
  240.             ASSERT(lpType->typekind == TKIND_COCLASS);
  241.  
  242.             UINT nCount;
  243.             int iFlags;
  244.             HREFTYPE hRefType;
  245.  
  246.             //
  247.             //  Search for typeinfo of the default events interface.
  248.             //
  249.  
  250.             for (nCount = 0; nCount < lpType->cImplTypes; nCount++)
  251.             {
  252.                if (SUCCEEDED(lpClassInfo->GetImplTypeFlags(nCount, &iFlags)) &&
  253.                   ((iFlags & IMPLTYPE_MASK) == IMPLTYPE_DEFAULTSOURCE))
  254.                {
  255.                   LPTYPEINFO lpTypeInfo = NULL;
  256.  
  257.                   if (SUCCEEDED(lpClassInfo->GetRefTypeOfImplType(nCount, &hRefType)) &&
  258.                       SUCCEEDED(lpClassInfo->GetRefTypeInfo(hRefType, &lpTypeInfo)))
  259.                   {
  260.                      //
  261.                      //  Found it!  Use it to initialize event table.
  262.                      //
  263.  
  264.                      ASSERT(lpTypeInfo != NULL);
  265.                      InitEventInfo(lpTypeInfo);                           
  266.                      lpTypeInfo->Release();
  267.                      lpTypeInfo = NULL;
  268.                   }
  269.  
  270.                   break;
  271.                }
  272.             }
  273.  
  274.             lpClassInfo->ReleaseTypeAttr(lpType);
  275.              lpType = NULL;
  276.          }
  277.                 
  278.          lpClassInfo->Release();
  279.          lpClassInfo = NULL;
  280.       }
  281.  
  282.       lpProvide->Release();
  283.    }
  284. }
  285.  
  286.  
  287. /////////////////////////////////////////////////////////////////////////////
  288. //
  289. void CVogonCntrItem::FreeControlInfo(void)
  290. {
  291.    if (m_pEventInfo != NULL)
  292.    {
  293.       USHORT i;
  294.  
  295.       for (i = 0; i < m_nEvents; i++)
  296.       {
  297.          if (m_pEventInfo[i].pbstr != NULL)
  298.          {
  299.             for (SHORT j = 0; j < m_pEventInfo[i].cParams+1; j++)
  300.             {
  301.                ::SysFreeString(m_pEventInfo[i].pbstr[j]);
  302.             }
  303.             delete [] m_pEventInfo[i].pbstr;
  304.          }
  305.       }
  306.       delete [] m_pEventInfo;
  307.       m_pEventInfo = NULL;
  308.    }                            
  309. }
  310.  
  311. /////////////////////////////////////////////////////////////////////////////
  312. //
  313. EVENTINFO* CVogonCntrItem::GetEventInfo(MEMBERID memid)
  314. {
  315.    USHORT i;
  316.  
  317.    for (i = 0; i < m_nEvents; i++)
  318.    {
  319.       if (memid == m_pEventInfo[i].memid)
  320.       {
  321.          return &m_pEventInfo[i];
  322.       }
  323.    }    
  324.    return NULL;
  325. }
  326.                                    
  327.         
  328. /////////////////////////////////////////////////////////////////////////////
  329. //
  330. void CVogonCntrItem::CleanUpParams()
  331. {              
  332.    ASSERT_VALID(this);          
  333.  
  334.    DISPPARAMS FAR* lpDispparams = &m_LastParams;
  335.    
  336.    if (lpDispparams->rgvarg != NULL)          
  337.    {
  338.       for (UINT i=0; i<lpDispparams->cArgs; i++)
  339.       {
  340.          switch(lpDispparams->rgvarg[i].vt)
  341.          {
  342.             case VT_BSTR:
  343.                ::SysFreeString(lpDispparams->rgvarg[i].bstrVal);
  344.                break;
  345.             case VT_DISPATCH:
  346.                lpDispparams->rgvarg[i].pdispVal->Release();
  347.                break;
  348.             case VT_UNKNOWN:
  349.                lpDispparams->rgvarg[i].punkVal->Release();
  350.                break;
  351.             default:
  352.                break;
  353.          }
  354.       }
  355.       delete lpDispparams->rgvarg;
  356.    }
  357.  
  358.    lpDispparams->rgvarg = NULL;
  359.  
  360.    if (lpDispparams->rgdispidNamedArgs != NULL)
  361.    {
  362.       delete lpDispparams->rgdispidNamedArgs;
  363.    }
  364.    lpDispparams->rgdispidNamedArgs = NULL;
  365. }        
  366.                                  
  367. /////////////////////////////////////////////////////////////////////////////
  368. //
  369. void CVogonCntrItem::CopyParams(DISPPARAMS FAR* lpDispparams)
  370. {       
  371.     UINT i;             
  372.  
  373.     if (lpDispparams == NULL)
  374.         return;                    // can't copy bogus params
  375.         
  376.     if (m_LastParams.cArgs > 0)
  377.         CleanUpParams();
  378.  
  379.     // Change state information about incoming                           
  380.     m_LastParams.cArgs = lpDispparams->cArgs;    
  381.     if (lpDispparams->cArgs == 0)
  382.         m_LastParams.rgvarg = NULL;
  383.     else
  384.         m_LastParams.rgvarg = new VARIANTARG[lpDispparams->cArgs];
  385.     
  386.     m_LastParams.cNamedArgs = lpDispparams->cNamedArgs;
  387.     if(lpDispparams->cNamedArgs == 0)
  388.           m_LastParams.rgdispidNamedArgs = NULL;
  389.     else
  390.     {
  391.           m_LastParams.rgdispidNamedArgs = new DISPID[lpDispparams->cNamedArgs];
  392.               
  393.         for(i = 0; i < m_LastParams.cNamedArgs; ++i)
  394.             m_LastParams.rgdispidNamedArgs[i] = lpDispparams->rgdispidNamedArgs[i];
  395.     }
  396.     
  397.     for (i = 0; i < m_LastParams.cArgs; i++)
  398.     {               
  399.         // Copy Parameter by type, left-to-right
  400.       int indexOut = m_LastParams.cArgs - i - 1; 
  401.  
  402.         m_LastParams.rgvarg[indexOut].vt = lpDispparams->rgvarg[i].vt;
  403.  
  404.         switch(lpDispparams->rgvarg[i].vt)
  405.         {       
  406.             case VT_I2:
  407.                 m_LastParams.rgvarg[indexOut].iVal = lpDispparams->rgvarg[i].iVal;
  408.                 break;
  409.      
  410.             case VT_I4:
  411.                 m_LastParams.rgvarg[indexOut].lVal = lpDispparams->rgvarg[i].lVal;
  412.                 break;
  413.      
  414.             case VT_R4:
  415.                 m_LastParams.rgvarg[indexOut].fltVal = lpDispparams->rgvarg[i].fltVal;
  416.                 break;
  417.      
  418.             case VT_R8:
  419.                 m_LastParams.rgvarg[indexOut].dblVal = lpDispparams->rgvarg[i].dblVal;
  420.                 break;
  421.  
  422.             case VT_BOOL:
  423.                 m_LastParams.rgvarg[indexOut].bool = lpDispparams->rgvarg[i].bool;
  424.                 break;
  425.                                                                           
  426.             case VT_ERROR:
  427.                 m_LastParams.rgvarg[indexOut].scode = lpDispparams->rgvarg[i].scode;
  428.                 break;
  429.                                                                             
  430.             case VT_CY:
  431.                 m_LastParams.rgvarg[indexOut].cyVal = lpDispparams->rgvarg[i].cyVal;
  432.                 break;
  433.  
  434.             case VT_DATE:
  435.                 m_LastParams.rgvarg[indexOut].date = lpDispparams->rgvarg[i].date;
  436.                 break;
  437.                 
  438.             case VT_BSTR:
  439.                 m_LastParams.rgvarg[indexOut].bstrVal = ::SysAllocString(lpDispparams->rgvarg[i].bstrVal);
  440.                 break;
  441.                                                                              
  442.             case VT_UNKNOWN:
  443.                 m_LastParams.rgvarg[indexOut].punkVal = lpDispparams->rgvarg[i].punkVal;
  444.                 break;
  445.                                                                                 
  446.             case VT_DISPATCH:
  447.                 m_LastParams.rgvarg[indexOut].pdispVal = lpDispparams->rgvarg[i].pdispVal;
  448.                 break;
  449.                 
  450.             case (VT_I2 | VT_BYREF):
  451.                 m_LastParams.rgvarg[indexOut].piVal = lpDispparams->rgvarg[i].piVal;
  452.                 break;
  453.                 
  454.             case (VT_I4 | VT_BYREF):
  455.                 m_LastParams.rgvarg[indexOut].plVal = lpDispparams->rgvarg[i].plVal;
  456.                 break;
  457.                 
  458.             case (VT_R4 | VT_BYREF):
  459.                 m_LastParams.rgvarg[indexOut].pfltVal = lpDispparams->rgvarg[i].pfltVal;
  460.                 break;
  461.  
  462.             case (VT_R8 | VT_BYREF):
  463.                 m_LastParams.rgvarg[indexOut].pdblVal = lpDispparams->rgvarg[i].pdblVal;
  464.                 break;
  465.  
  466.             case (VT_BOOL | VT_BYREF):
  467.                 m_LastParams.rgvarg[indexOut].pbool = lpDispparams->rgvarg[i].pbool;
  468.                 break;
  469.                                                                           
  470.             case (VT_ERROR | VT_BYREF):
  471.                 m_LastParams.rgvarg[indexOut].pscode = lpDispparams->rgvarg[i].pscode;
  472.                 break;
  473.                                                                             
  474.             case (VT_CY | VT_BYREF):
  475.                 m_LastParams.rgvarg[indexOut].pcyVal = lpDispparams->rgvarg[i].pcyVal;
  476.                 break;
  477.  
  478.             case (VT_DATE | VT_BYREF):
  479.                 m_LastParams.rgvarg[indexOut].pdate = lpDispparams->rgvarg[i].pdate;
  480.                 break;
  481.                 
  482.             case (VT_BSTR | VT_BYREF):
  483.                 m_LastParams.rgvarg[indexOut].pbstrVal = lpDispparams->rgvarg[i].pbstrVal;
  484.                 break;
  485.                              
  486.             case (VT_VARIANT | VT_BYREF):
  487.                 m_LastParams.rgvarg[indexOut].pvarVal = lpDispparams->rgvarg[i].pvarVal;
  488.                 break;
  489.                                                                                              
  490.             case (VT_UNKNOWN | VT_BYREF):
  491.                 m_LastParams.rgvarg[indexOut].ppunkVal = lpDispparams->rgvarg[i].ppunkVal;
  492.                 break;
  493.                                                                                 
  494.             case (VT_DISPATCH | VT_BYREF):
  495.                 m_LastParams.rgvarg[indexOut].ppdispVal = lpDispparams->rgvarg[i].ppdispVal;
  496.                 break;
  497.                 
  498.             default:
  499.                 break;
  500.         }
  501.     }
  502. }
  503.                                           
  504. /////////////////////////////////////////////////////////////////////////////
  505. //  Callbacks
  506.  
  507. void CVogonCntrItem::OnEvent(DISPID dispID, DISPPARAMS FAR* lpDispparams)
  508. {
  509.    // Set the dispid and dispparams pointers to the latest information
  510.  
  511.    m_EventID = dispID;
  512.    CopyParams(lpDispparams);
  513.  
  514. #ifdef MAJOR_DEBUG
  515.    TRACE("CVogonCntrItem dispatched for event %ld\n", dispID);
  516.  
  517.    // find the event
  518.    EVENTINFO* pEvent = GetEventInfo(m_EventID);
  519.    // Did we ?
  520.    if (pEvent == NULL)
  521.    { 
  522.       TRACE1("Unknown event ID: %u\n", m_EventID);
  523.       return;
  524.    }
  525.  
  526.    // Costruct the trace: start with the event name
  527.    CString stringMsg(pEvent->pbstr[0]);
  528.    // wcstombs(sz, (const unsigned short*) pEvent->pbstr[0], ELEMENTS(sz));
  529.    stringMsg += _T("(");
  530.  
  531.    for (unsigned nParameter = 0; nParameter < m_LastParams.cArgs; nParameter++)
  532.    {
  533.       TCHAR fmtBuf[64];
  534.  
  535.       if (nParameter > 0)
  536.       {
  537.          stringMsg += _T(", ");
  538.       }
  539.  
  540.       stringMsg += pEvent->pbstr[nParameter + 1];
  541.       stringMsg += _T(" = ");
  542.  
  543.       // We only handle BSTR, LONG, SHORT and BOOL - the types Webster uses ...
  544.       switch (m_LastParams.rgvarg[nParameter].vt)
  545.       {  // These are define in OLEAuto.h ..
  546.          case VT_I2:
  547.             // m_LastParams.rgvarg[i].iVal = lpDispparams->rgvarg[i].iVal;
  548.             TRACE("VT_I2 = %hu\n", m_LastParams.rgvarg[nParameter].iVal);
  549.             stringMsg += itoa(m_LastParams.rgvarg[nParameter].iVal, fmtBuf, 10);
  550.             break;
  551.  
  552.          case VT_I4:
  553.             // m_LastParams.rgvarg[i].lVal = lpDispparams->rgvarg[i].lVal;
  554.             TRACE("VT_I4 = %lu\n", m_LastParams.rgvarg[nParameter].lVal);
  555.             stringMsg += ltoa(m_LastParams.rgvarg[nParameter].iVal, fmtBuf, 10);
  556.             break;
  557.  
  558.          case VT_BSTR:
  559.             // m_LastParams.rgvarg[i].bstrVal = ::SysAllocString(lpDispparams->rgvarg[i].bstrVal);
  560.             TRACE("VT_BSTR = %s\n", (LPCTSTR) m_LastParams.rgvarg[nParameter].bstrVal);
  561.             break;
  562.  
  563.          case VT_BOOL:
  564.             // m_LastParams.rgvarg[i].bool = lpDispparams->rgvarg[i].bool;
  565.             TRACE("VT_BOOL = %s\n", m_LastParams.rgvarg[nParameter].bool ? _T("TRUE") : _T("FALSE"));
  566.             stringMsg += m_LastParams.rgvarg[nParameter].bool ? _T("TRUE") : _T("FALSE");
  567.             break;
  568.                                                                           
  569.          case VT_I2 | VT_BYREF:
  570.             // m_LastParams.rgvarg[i].iVal = lpDispparams->rgvarg[i].iVal;
  571.             TRACE("VT_I2 | VT_BYREF = %hu\n", *m_LastParams.rgvarg[nParameter].piVal);
  572.             stringMsg += itoa(*m_LastParams.rgvarg[nParameter].piVal, fmtBuf, 10);
  573.             break;
  574.  
  575.          case VT_I4 | VT_BYREF:
  576.             // m_LastParams.rgvarg[i].lVal = lpDispparams->rgvarg[i].lVal;
  577.             TRACE("VT_I4 | VT_BYREF = %lu\n", *m_LastParams.rgvarg[nParameter].plVal);
  578.             stringMsg += ltoa(*m_LastParams.rgvarg[nParameter].piVal, fmtBuf, 10);
  579.             break;
  580.  
  581.          case VT_BSTR | VT_BYREF:
  582.             // m_LastParams.rgvarg[i].bstrVal = ::SysAllocString(lpDispparams->rgvarg[i].bstrVal);
  583.             TRACE("VT_BSTR | VT_BYREF = %s\n", *(LPCTSTR*) m_LastParams.rgvarg[nParameter].pbstrVal);
  584.             stringMsg += *(LPCTSTR*) m_LastParams.rgvarg[nParameter].bstrVal;
  585.             break;
  586.  
  587.          case VT_BOOL | VT_BYREF:
  588.             // m_LastParams.rgvarg[i].bool = lpDispparams->rgvarg[i].bool;
  589.             TRACE("VT_BOOL | VT_BYREF = %s\n", (*m_LastParams.rgvarg[nParameter].pbool ? _T("TRUE") : _T("FALSE")));
  590.             stringMsg += (*m_LastParams.rgvarg[nParameter].pbool ? _T("TRUE") : _T("FALSE"));
  591.             break;
  592.                                                                           
  593.       }
  594.    }
  595.  
  596.    stringMsg += _T(")\n");
  597.    TRACE(stringMsg);
  598. #endif // MAJOR_DEBUG
  599.  
  600.    // Get pointer to our document
  601.    CVogonDoc* pDoc = (CVogonDoc*) GetDocument();
  602.    ASSERT(pDoc);
  603.  
  604.    // This event id list is hard-coded for Webster - pick up the latest values from webster.cpp
  605.    #define EVENT_INDEX_DOCLICKURL   (0x1)
  606.    #define EVENT_INDEX_KEYDOWN      (0xfffffda6)
  607.    #define EVENT_INDEX_LOADCOMPLETE (0x2)
  608.  
  609.    // Which event routine to call ?
  610.    switch (m_EventID)
  611.    {
  612.       case EVENT_INDEX_DOCLICKURL:
  613.          // eventDoClickURL(BSTR* SelectedURL, BOOL* Cancel);
  614.          pDoc->eventDoClickURL(m_LastParams.rgvarg[0].pbstrVal, m_LastParams.rgvarg[1].pbool);
  615.          break;
  616.  
  617.       case EVENT_INDEX_KEYDOWN:
  618.          // eventKeyDown(short* KeyCode, short Shift);
  619.          pDoc->eventKeyDown(m_LastParams.rgvarg[0].piVal, m_LastParams.rgvarg[1].iVal);
  620.          break;
  621.  
  622.       case EVENT_INDEX_LOADCOMPLETE:
  623.          // eventLoadComplete(BSTR* pageURL, short Status);
  624.          pDoc->eventLoadComplete(m_LastParams.rgvarg[0].pbstrVal, m_LastParams.rgvarg[1].iVal);
  625.          break;
  626.    }
  627. }
  628.  
  629. #ifdef JUST_FOR_REFERENCE
  630. typedef struct  tagDISPPARAMS
  631.     {
  632.     /* [size_is] */ VARIANTARG __RPC_FAR *rgvarg;
  633.     /* [size_is] */ DISPID __RPC_FAR *rgdispidNamedArgs;
  634.     UINT cArgs;
  635.     UINT cNamedArgs;
  636.     }    DISPPARAMS;
  637.  
  638. struct tagVARIANT{
  639.     VARTYPE vt;
  640.     WORD wReserved1;
  641.     WORD wReserved2;
  642.     WORD wReserved3;
  643.     union
  644.     {
  645.       unsigned char bVal;           /* VT_UI1               */
  646.       short         iVal;           /* VT_I2                */
  647.       long          lVal;           /* VT_I4                */
  648.       float         fltVal;         /* VT_R4                */
  649.       double        dblVal;         /* VT_R8                */
  650.       VARIANT_BOOL  bool;           /* VT_BOOL              */
  651.       SCODE         scode;          /* VT_ERROR             */
  652.       CY            cyVal;          /* VT_CY                */
  653.       DATE          date;           /* VT_DATE              */
  654.       BSTR          bstrVal;        /* VT_BSTR              */
  655.       IUnknown      *punkVal;       /* VT_UNKNOWN           */
  656.       IDispatch     *pdispVal;      /* VT_DISPATCH          */
  657.       SAFEARRAY     *parray;        /* VT_ARRAY|*           */
  658.       unsigned char *pbVal;         /* VT_BYREF|VT_UI1      */
  659.       short         *piVal;         /* VT_BYREF|VT_I2       */
  660.       long          *plVal;         /* VT_BYREF|VT_I4       */
  661.       float         *pfltVal;       /* VT_BYREF|VT_R4       */
  662.       double        *pdblVal;       /* VT_BYREF|VT_R8       */
  663.       VARIANT_BOOL  *pbool;         /* VT_BYREF|VT_BOOL     */
  664.       SCODE         *pscode;        /* VT_BYREF|VT_ERROR    */
  665.       CY            *pcyVal;        /* VT_BYREF|VT_CY       */
  666.       DATE          *pdate;         /* VT_BYREF|VT_DATE     */
  667.       BSTR          *pbstrVal;      /* VT_BYREF|VT_BSTR     */
  668.       IUnknown      **ppunkVal;     /* VT_BYREF|VT_UNKNOWN  */
  669.       IDispatch     **ppdispVal;    /* VT_BYREF|VT_DISPATCH */
  670.       SAFEARRAY     **pparray;      /* VT_BYREF|VT_ARRAY|*  */
  671.       VARIANT       *pvarVal;       /* VT_BYREF|VT_VARIANT  */
  672.       void     * byref;             /* Generic ByRef        */
  673.     }
  674. #if(defined(NONAMELESSUNION))
  675.     u
  676. #endif
  677.      ;
  678. };
  679. #endif // JUST_FOR_REFERENCE
  680.  
  681. /////////////////////////////////////////////////////////////////////////////
  682. //  CVogonCntrItem::XEventHandler
  683.  
  684.  
  685. STDMETHODIMP_(ULONG) CVogonCntrItem::XEventHandler::AddRef()
  686. {
  687.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  688.     return (ULONG)pThis->ExternalAddRef();
  689. }
  690.  
  691.  
  692. STDMETHODIMP_(ULONG) CVogonCntrItem::XEventHandler::Release()
  693. {
  694.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  695.     return (ULONG)pThis->ExternalRelease();
  696. }
  697.  
  698.  
  699. STDMETHODIMP CVogonCntrItem::XEventHandler::QueryInterface(
  700.     REFIID iid, LPVOID far* ppvObj)
  701. {
  702.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  703.     return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
  704. }
  705.  
  706.  
  707. STDMETHODIMP CVogonCntrItem::XEventHandler::GetTypeInfoCount(unsigned int FAR* pctinfo)
  708. {
  709.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  710.     ASSERT_VALID(pThis);
  711.  
  712.     *pctinfo = 0;
  713.     return NOERROR;
  714. }
  715.  
  716.  
  717. STDMETHODIMP CVogonCntrItem::XEventHandler::GetTypeInfo(unsigned int itinfo,
  718.       LCID lcid, ITypeInfo FAR* FAR* pptinfo)
  719. {
  720.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  721.     ASSERT_VALID(pThis);
  722.  
  723.     return ResultFromScode(E_NOTIMPL);
  724. }
  725.  
  726.  
  727. STDMETHODIMP CVogonCntrItem::XEventHandler::GetIDsOfNames(REFIID riid,
  728.       LPTSTR FAR* rgszNames, unsigned int cNames, LCID lcid,
  729.       DISPID FAR* rgdispid)
  730. {
  731.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  732.     ASSERT_VALID(pThis);
  733.  
  734.     return ResultFromScode(E_NOTIMPL);
  735. }
  736.  
  737.  
  738. STDMETHODIMP CVogonCntrItem::XEventHandler::Invoke(DISPID dispidMember,
  739.       REFIID riid, LCID lcid, unsigned short wFlags, DISPPARAMS FAR* lpDispparams,
  740.       VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo, 
  741.       unsigned int FAR* puArgErr)
  742. {
  743.     METHOD_PROLOGUE(CVogonCntrItem, EventHandler)
  744.     ASSERT_VALID(pThis);
  745.  
  746.     pThis->OnEvent(dispidMember, lpDispparams);    // Call the event handler, who also cleans up.
  747.     
  748.     return NOERROR;
  749. }
  750.                                           
  751.  
  752. /////////////////////////////////////////////////////////////////////////////
  753. // 
  754. void CVogonCntrItem::OnActivate()
  755. {
  756.    // Let the base class do it's thing
  757.    COleClientItem::OnActivate();
  758.    // Create a dispatch interface for our Webster:
  759.    LPDISPATCH pd = GetIDispatch();
  760.    TRACE("CVogonCntrItem::OnActivate IDispatch at %x\n", pd);
  761.    m_dWebster.AttachDispatch(pd);
  762. }
  763.  
  764. /////////////////////////////////////////////////////////////////////////////
  765. // 
  766. void CVogonCntrItem::OnDeactivate()
  767. {
  768.    // Let the base class do it's thing
  769.    COleClientItem::OnDeactivate();
  770.    // Release the dispatch interface for our Webster:
  771.    m_dWebster.ReleaseDispatch();
  772. }
  773.  
  774. void CVogonCntrItem::OnChange(OLE_NOTIFICATION nCode, DWORD dwParam)
  775. {
  776.    ASSERT_VALID(this);
  777.  
  778.    COleClientItem::OnChange(nCode, dwParam);
  779.  
  780.    // When an item is being edited (either in-place or fully open)
  781.    //  it sends OnChange notifications for changes in the state of the
  782.    //  item or visual appearance of its content.
  783.  
  784.    // TODO: invalidate the item by calling UpdateAllViews
  785.    //  (with hints appropriate to your application)
  786.  
  787.    GetDocument()->UpdateAllViews(NULL);
  788.       // for now just update ALL views/no hints
  789. }
  790.  
  791. BOOL CVogonCntrItem::OnChangeItemPosition(const CRect& rectPos)
  792. {
  793.    ASSERT_VALID(this);
  794.  
  795.    // During in-place activation CVogonCntrItem::OnChangeItemPosition
  796.    //  is called by the server to change the position on of the in-place
  797.    //  window.  Usually, this is a result of the data in the server
  798.    //  document changing such that the extent has changed or as a result
  799.    //  of in-place resizing.
  800.    //
  801.    // The default here is to call the base class, which will call
  802.    //  COleClientItem::SetItemRects to move the item
  803.    //  to the new position.
  804.  
  805.    if (IsInPlaceActive() && !COleClientItem::OnChangeItemPosition(rectPos))
  806.       return FALSE;
  807.  
  808.    // TODO: update any cache you may have of the item's rectangle/extent
  809.  
  810.    return TRUE;
  811. }
  812.  
  813. void CVogonCntrItem::OnGetItemPosition(CRect& rPosition)
  814. {
  815.    ASSERT_VALID(this);
  816.  
  817.    // During in-place activation, CVogonCntrItem::OnGetItemPosition
  818.    //  will be called to determine the location of this item.  The default
  819.    //  implementation created from AppWizard simply returns a hard-coded
  820.    //  rectangle.  Usually, this rectangle would reflect the current
  821.    //  position of the item relative to the view used for activation.
  822.    //  You can obtain the view by calling CVogonCntrItem::GetActiveView.
  823.  
  824.  
  825.    // We always fill our view:
  826.    if (GetInPlaceWindow())
  827.    {  // Object has a window: just get the current size
  828.       GetInPlaceWindow()->GetWindowRect(rPosition);
  829.    }
  830.    else
  831.    {  // Just fill the view
  832.       GetActiveView()->GetClientRect(rPosition);
  833.    }
  834.    // TODO: return correct rectangle (in pixels) in rectPos
  835.  
  836.    // rPosition.SetRect(10, 10, 210, 210);
  837. }
  838.  
  839. void CVogonCntrItem::OnDeactivateUI(BOOL bUndoable)
  840. {
  841.    COleClientItem::OnDeactivateUI(bUndoable);
  842.  
  843.    // Close an in-place active item whenever it removes the user
  844.    //  interface.  The action here should match as closely as possible
  845.    //  to the handling of the escape key in the view.
  846.  
  847.    Deactivate();   // nothing fancy here -- just deactivate the object
  848. }
  849.  
  850. void CVogonCntrItem::Serialize(CArchive& ar)
  851. {
  852.    ASSERT_VALID(this);
  853.  
  854.    // Call base class first to read in COleClientItem data.
  855.    // Since this sets up the m_pDocument pointer returned from
  856.    //  CVogonCntrItem::GetDocument, it is a good idea to call
  857.    //  the base class Serialize first.
  858.    COleClientItem::Serialize(ar);
  859.  
  860.    // now store/retrieve data specific to CVogonCntrItem
  861.    if (ar.IsStoring())
  862.    {
  863.       // TODO: add storing code here
  864.    }
  865.    else
  866.    {  
  867.       // TODO: add loading code here
  868.    }
  869. }
  870.  
  871. /////////////////////////////////////////////////////////////////////////////
  872. // CVogonCntrItem diagnostics
  873.  
  874. #ifdef _DEBUG
  875. void CVogonCntrItem::AssertValid() const
  876. {
  877.    COleClientItem::AssertValid();
  878. }
  879.  
  880. void CVogonCntrItem::Dump(CDumpContext& dc) const
  881. {
  882.    COleClientItem::Dump(dc);
  883. }
  884. #endif
  885.  
  886. /////////////////////////////////////////////////////////////////////////////
  887. //  This code is straight outa MSDN ...
  888. //
  889. LPDISPATCH CVogonCntrItem::GetIDispatch()
  890. {
  891.    ASSERT_VALID(this);
  892.    ASSERT(m_lpObject != NULL);
  893.  
  894.    LPUNKNOWN lpUnk = m_lpObject;
  895.  
  896.    Run();    // must be running
  897.  
  898.    LPOLELINK lpOleLink = NULL;
  899.    if (m_lpObject->QueryInterface(IID_IOleLink, (LPVOID FAR*)&lpOleLink) == NOERROR)
  900.    {
  901.       ASSERT(lpOleLink != NULL);
  902.       lpUnk = NULL;
  903.       if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
  904.       {
  905.          TRACE0("Warning: Link is not connected!\n");
  906.          lpOleLink->Release();
  907.          return NULL;
  908.       }
  909.       ASSERT(lpUnk != NULL);
  910.    }
  911.  
  912.    LPDISPATCH lpDispatch = NULL;
  913.    if (lpUnk->QueryInterface(IID_IDispatch, (void**) &lpDispatch) != NOERROR)
  914.    {
  915.       TRACE0("Warning: does not support IDispatch!\n");
  916.       return NULL;
  917.    }
  918.  
  919.    ASSERT(lpDispatch != NULL);
  920.    return lpDispatch;
  921. }
  922.  
  923.