home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / com / inole2 / chap04 / connect / object.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  10KB  |  490 lines

  1. /*
  2.  * OBJECT.CPP
  3.  *
  4.  * Connectable Object implementation that supports the sample
  5.  * interface IDuckEvents.
  6.  *
  7.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  8.  *
  9.  * Kraig Brockschmidt, Microsoft
  10.  * Internet  :  kraigb@microsoft.com
  11.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  12.  */
  13.  
  14.  
  15. #include "connect.h"
  16.  
  17.  
  18. /*
  19.  * CConnObject::CConnObject
  20.  * CConnObject::~CConnObject
  21.  *
  22.  * Constructor Parameters:
  23.  *  None
  24.  */
  25.  
  26. CConnObject::CConnObject(void)
  27.     {
  28.     UINT        i;
  29.  
  30.     m_cRef=0;
  31.  
  32.     for (i=0; i < CCONNPOINTS; i++)
  33.         m_rgpConnPt[i]=NULL;
  34.  
  35.     return;
  36.     }
  37.  
  38. CConnObject::~CConnObject(void)
  39.     {
  40.     UINT    i;
  41.  
  42.     for (i=0; i < CCONNPOINTS; i++)
  43.         {
  44.         if (NULL!=m_rgpConnPt[i])
  45.             {
  46.             if (NULL!=m_rgpConnPt[i])
  47.                 delete m_rgpConnPt[i];
  48.             }
  49.         }
  50.  
  51.     return;
  52.     }
  53.  
  54.  
  55.  
  56. /*
  57.  * CConnObject::Init
  58.  *
  59.  * Purpose:
  60.  *  Instantiates the interface implementations for this object.
  61.  *
  62.  * Parameters:
  63.  *  None
  64.  *
  65.  * Return Value:
  66.  *  BOOL            TRUE if initialization succeeds, FALSE otherwise.
  67.  */
  68.  
  69. BOOL CConnObject::Init(void)
  70.     {
  71.     UINT    i;
  72.  
  73.     //Create our connection points
  74.     for (i=0; i < CCONNPOINTS; i++)
  75.         {
  76.         m_rgpConnPt[i]=new CConnectionPoint(this, IID_IDuckEvents);
  77.  
  78.         if (NULL==m_rgpConnPt[i])
  79.             return FALSE;
  80.  
  81.         m_rgpConnPt[i]->AddRef();
  82.         }
  83.  
  84.     return TRUE;
  85.     }
  86.  
  87.  
  88.  
  89. /*
  90.  * CConnObject::QueryInterface
  91.  *
  92.  * Purpose:
  93.  *  Manages the interfaces for this object which supports the
  94.  *  IUnknown, ISampleOne, and ISampleTwo interfaces.
  95.  *
  96.  * Parameters:
  97.  *  riid            REFIID of the interface to return.
  98.  *  ppv             PPVOID in which to store the pointer.
  99.  *
  100.  * Return Value:
  101.  *  HRESULT         NOERROR on success, E_NOINTERFACE if the
  102.  *                  interface is not supported.
  103.  */
  104.  
  105. STDMETHODIMP CConnObject::QueryInterface(REFIID riid, PPVOID ppv)
  106.     {
  107.     //Always NULL the out-parameters
  108.     *ppv=NULL;
  109.  
  110.     if (IID_IUnknown==riid || IID_IConnectionPointContainer==riid)
  111.         *ppv=this;
  112.  
  113.     if (NULL==*ppv)
  114.         return ResultFromScode(E_NOINTERFACE);
  115.  
  116.     ((LPUNKNOWN)*ppv)->AddRef();
  117.     return NOERROR;
  118.     }
  119.  
  120.  
  121.  
  122. /*
  123.  * CConnObject::AddRef
  124.  * CConnObject::Release
  125.  *
  126.  * Reference counting members.  When Release sees a zero count
  127.  * the object destroys itself.
  128.  */
  129.  
  130. DWORD CConnObject::AddRef(void)
  131.     {
  132.     return ++m_cRef;
  133.     }
  134.  
  135. DWORD CConnObject::Release(void)
  136.     {
  137.     if (0!=--m_cRef)
  138.         return m_cRef;
  139.  
  140.     delete this;
  141.     return 0;
  142.     }
  143.  
  144.  
  145.  
  146. /*
  147.  * CConnObject::EnumConnectionPoints
  148.  *
  149.  * Purpose:
  150.  *  Creates and returns an enumerator object with the
  151.  *  IEnumConnectionPoints interface that will enumerate the
  152.  *  individual connection points supported in this object.
  153.  *
  154.  * Parameters:
  155.  *  ppEnum          LPENUMCONNECTIONPOINTS in which to store the
  156.  *                  IEnumConnectionPoints pointer.
  157.  *
  158.  * Return Value:
  159.  *  HRESULT         NOERROR on success, E_OUTOFMEMORY on failure or
  160.  *                  other error code.
  161.  */
  162.  
  163. STDMETHODIMP CConnObject::EnumConnectionPoints
  164.     (LPENUMCONNECTIONPOINTS *ppEnum)
  165.     {
  166.     IConnectionPoint       *rgCP[CCONNPOINTS];
  167.     UINT                    i;
  168.     PCEnumConnectionPoints  pEnum;
  169.  
  170.     *ppEnum=NULL;
  171.  
  172.     for (i=0; i < CCONNPOINTS; i++)
  173.         rgCP[i]=(IConnectionPoint *)m_rgpConnPt[i];
  174.  
  175.     //Create the enumerator:  we only have one connection point
  176.     pEnum=new CEnumConnectionPoints(this, CCONNPOINTS, rgCP);
  177.  
  178.     if (NULL==pEnum)
  179.         return ResultFromScode(E_OUTOFMEMORY);
  180.  
  181.     pEnum->AddRef();
  182.     *ppEnum=pEnum;
  183.     return NOERROR;
  184.     }
  185.  
  186.  
  187.  
  188. /*
  189.  * CConnObject::FindConnectionPoint
  190.  *
  191.  * Purpose:
  192.  *  Returns a pointer to the IConnectionPoint for a given
  193.  *  outgoing IID.
  194.  *
  195.  * Parameters:
  196.  *  riid            REFIID of the outgoing interface for which
  197.  *                  a connection point is desired.
  198.  *  ppCP            IConnectionPoint ** in which to return
  199.  *                  the pointer after calling AddRef.
  200.  *
  201.  * Return Value:
  202.  *  HRESULT         NOERROR if the connection point is found,
  203.  *                  E_NOINTERFACE if it's not supported.
  204.  */
  205.  
  206. STDMETHODIMP CConnObject::FindConnectionPoint(REFIID riid
  207.     , IConnectionPoint **ppCP)
  208.     {
  209.     *ppCP=NULL;
  210.  
  211.     if (IID_IDuckEvents==riid)
  212.         {
  213.         return m_rgpConnPt[0]->QueryInterface(IID_IConnectionPoint
  214.             , (PPVOID)ppCP);
  215.         }
  216.  
  217.     return ResultFromScode(E_NOINTERFACE);
  218.     }
  219.  
  220.  
  221.  
  222. /*
  223.  * CConnObject::TriggerEvent
  224.  *
  225.  * Purpose:
  226.  *  Functions to make each connection point generate calls
  227.  *  to any connected sinks.  Since these functions are specific
  228.  *  to IDuckEvents, they only deal with the connection point
  229.  *  for that one interface
  230.  *
  231.  * Parameters:
  232.  *  iEvent          UINT of the event to trigger, either
  233.  *                  EVENT_QUACK, EVENT_FLAP, or EVENT_PADDLE.
  234.  *
  235.  * Return Value:
  236.  *  BOOL            TRUE events are triggered, FALSE if there
  237.  *                  are no connected sinks.
  238.  */
  239.  
  240. BOOL CConnObject::TriggerEvent(UINT iEvent)
  241.     {
  242.     IEnumConnections   *pEnum;
  243.     CONNECTDATA         cd;
  244.  
  245.     if (FAILED(m_rgpConnPt[0]->EnumConnections(&pEnum)))
  246.         return FALSE;
  247.  
  248.     while (NOERROR==pEnum->Next(1, &cd, NULL))
  249.         {
  250.         IDuckEvents    *pDuck;
  251.  
  252.         if (SUCCEEDED(cd.pUnk->QueryInterface(IID_IDuckEvents
  253.             , (PPVOID)&pDuck)))
  254.             {
  255.             switch (iEvent)
  256.                 {
  257.                 case EVENT_QUACK:
  258.                     pDuck->Quack();
  259.                     break;
  260.  
  261.                 case EVENT_FLAP:
  262.                     pDuck->Flap();
  263.                     break;
  264.  
  265.                 case EVENT_PADDLE:
  266.                     pDuck->Paddle();
  267.                     break;
  268.                 }
  269.  
  270.             pDuck->Release();
  271.             }
  272.  
  273.         cd.pUnk->Release();
  274.         }
  275.  
  276.     pEnum->Release();
  277.     return TRUE;
  278.     }
  279.  
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286. //Connection Point Enumerator follows
  287.  
  288.  
  289. /*
  290.  * CEnumConnectionPoints::CEnumConnectionPoints
  291.  * CEnumConnectionPoints::~CEnumConnectionPoints
  292.  *
  293.  * Parameters (Constructor):
  294.  *  pUnkRef         LPUNKNOWN to use for reference counting.
  295.  *  cPoints         ULONG number of connection points in prgpCP
  296.  *  rgpCP           IConnectionPoint** to the array to enumerate.
  297.  */
  298.  
  299. CEnumConnectionPoints::CEnumConnectionPoints(LPUNKNOWN pUnkRef
  300.     , ULONG cPoints, IConnectionPoint **rgpCP)
  301.     {
  302.     UINT        i;
  303.  
  304.     m_cRef=0;
  305.     m_pUnkRef=pUnkRef;
  306.  
  307.     m_iCur=0;
  308.     m_cPoints=cPoints;
  309.     m_rgpCP=new IConnectionPoint *[(UINT)cPoints];
  310.  
  311.     if (NULL!=m_rgpCP)
  312.         {
  313.         for (i=0; i < cPoints; i++)
  314.             {
  315.             m_rgpCP[i]=rgpCP[i];
  316.             m_rgpCP[i]->AddRef();
  317.             }
  318.         }
  319.  
  320.     return;
  321.     }
  322.  
  323.  
  324. CEnumConnectionPoints::~CEnumConnectionPoints(void)
  325.     {
  326.     if (NULL!=m_rgpCP)
  327.         {
  328.         UINT        i;
  329.  
  330.         for (i=0; i < m_cPoints; i++)
  331.             m_rgpCP[i]->Release();
  332.  
  333.         delete [] m_rgpCP;
  334.         }
  335.  
  336.     return;
  337.     }
  338.  
  339.  
  340.  
  341.  
  342. /*
  343.  * CEnumConnectionPoints::QueryInterface
  344.  * CEnumConnectionPoints::AddRef
  345.  * CEnumConnectionPoints::Release
  346.  *
  347.  * Purpose:
  348.  *  IUnknown members for CEnumConnectionPoints object.
  349.  */
  350.  
  351. STDMETHODIMP CEnumConnectionPoints::QueryInterface(REFIID riid
  352.     , LPVOID *ppv)
  353.     {
  354.     *ppv=NULL;
  355.  
  356.     if (IID_IUnknown==riid || IID_IEnumConnectionPoints==riid)
  357.         *ppv=(LPVOID)this;
  358.  
  359.     if (NULL!=*ppv)
  360.         {
  361.         ((LPUNKNOWN)*ppv)->AddRef();
  362.         return NOERROR;
  363.         }
  364.  
  365.     return ResultFromScode(E_NOINTERFACE);
  366.     }
  367.  
  368.  
  369. STDMETHODIMP_(ULONG) CEnumConnectionPoints::AddRef(void)
  370.     {
  371.     ++m_cRef;
  372.     m_pUnkRef->AddRef();
  373.     return m_cRef;
  374.     }
  375.  
  376. STDMETHODIMP_(ULONG) CEnumConnectionPoints::Release(void)
  377.     {
  378.     m_pUnkRef->Release();
  379.  
  380.     if (0L!=--m_cRef)
  381.         return m_cRef;
  382.  
  383.     delete this;
  384.     return 0;
  385.     }
  386.  
  387.  
  388.  
  389.  
  390.  
  391. /*
  392.  * CEnumConnectionPoints::Next
  393.  *
  394.  * Purpose:
  395.  *  Returns the next element in the enumeration.
  396.  *
  397.  * Parameters:
  398.  *  cPoints         ULONG number of connection points to return.
  399.  *  ppCP            IConnectionPoint** in which to store the returned
  400.  *                  pointers.
  401.  *  pulEnum         ULONG * in which to return how many we
  402.  *                  enumerated.
  403.  *
  404.  * Return Value:
  405.  *  HRESULT         NOERROR if successful, S_FALSE otherwise,
  406.  */
  407.  
  408. STDMETHODIMP CEnumConnectionPoints::Next(ULONG cPoints
  409.     , IConnectionPoint **ppCP, ULONG *pulEnum)
  410.     {
  411.     ULONG               cReturn=0L;
  412.  
  413.     if (NULL==m_rgpCP)
  414.         return ResultFromScode(S_FALSE);
  415.  
  416.     if (NULL==ppCP)
  417.         return ResultFromScode(E_POINTER);
  418.  
  419.     if (NULL==pulEnum)
  420.         {
  421.         if (1L!=cPoints)
  422.             return ResultFromScode(E_POINTER);
  423.         }
  424.     else
  425.         *pulEnum=0L;
  426.  
  427.     if (NULL==*ppCP || m_iCur >= m_cPoints)
  428.         return ResultFromScode(S_FALSE);
  429.  
  430.     while (m_iCur < m_cPoints && cPoints > 0)
  431.         {
  432.         *ppCP=m_rgpCP[m_iCur++];
  433.  
  434.         if (NULL!=*ppCP)
  435.             (*ppCP)->AddRef();
  436.  
  437.         ppCP++;
  438.         cReturn++;
  439.         cPoints--;
  440.         }
  441.  
  442.     if (NULL!=pulEnum)
  443.         *pulEnum=cReturn;
  444.  
  445.     return NOERROR;
  446.     }
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.  
  454. STDMETHODIMP CEnumConnectionPoints::Skip(ULONG cSkip)
  455.     {
  456.     if (((m_iCur+cSkip) >= m_cPoints) || NULL==m_rgpCP)
  457.         return ResultFromScode(S_FALSE);
  458.  
  459.     m_iCur+=cSkip;
  460.     return NOERROR;
  461.     }
  462.  
  463.  
  464. STDMETHODIMP CEnumConnectionPoints::Reset(void)
  465.     {
  466.     m_iCur=0;
  467.     return NOERROR;
  468.     }
  469.  
  470.  
  471. STDMETHODIMP CEnumConnectionPoints::Clone
  472.     (LPENUMCONNECTIONPOINTS *ppEnum)
  473.     {
  474.     PCEnumConnectionPoints   pNew;
  475.  
  476.     *ppEnum=NULL;
  477.  
  478.     //Create the clone
  479.     pNew=new CEnumConnectionPoints(m_pUnkRef, m_cPoints, m_rgpCP);
  480.  
  481.     if (NULL==pNew)
  482.         return ResultFromScode(E_OUTOFMEMORY);
  483.  
  484.     pNew->AddRef();
  485.     pNew->m_iCur=m_iCur;
  486.  
  487.     *ppEnum=pNew;
  488.     return NOERROR;
  489.     }
  490.