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 / chap02 / enumrect / enumc.c next >
C/C++ Source or Header  |  1995-05-03  |  8KB  |  378 lines

  1. /*
  2.  * ENUMC.C
  3.  * Enumerator in C Chapter 2
  4.  *
  5.  * Implements the RECTENUMERATOR structure and functions (an object).
  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 "enumrect.h"
  16.  
  17.  
  18. //We have to explicitly define the function table for IEnumRECT in C
  19. static IEnumRECTVtbl  vtEnumRect;
  20. static BOOL           g_fVtblInitialized=FALSE;
  21.  
  22.  
  23. /*
  24.  * CreateRECTEnumeratorC
  25.  *
  26.  * Purpose:
  27.  *  Creates an enumerator object returning an IEnumRECT interface.
  28.  *
  29.  * Parameters:
  30.  *  ppEnum          PENUMRECT * in which to return the interface
  31.  *                  pointer on the created object.
  32.  *
  33.  * Return Value:
  34.  *  BOOL            TRUE if the function is successful,
  35.  *                  FALSE otherwise.
  36.  */
  37.  
  38. BOOL CreateRECTEnumeratorC(PENUMRECT *ppEnum)
  39.     {
  40.     PRECTENUMERATOR     pRE;
  41.     HRESULT             hr;
  42.  
  43.     if (NULL==ppEnum)
  44.         return FALSE;
  45.  
  46.     //Create the object
  47.     pRE=RECTENUM_Constructor();
  48.  
  49.     if (NULL==pRE)
  50.         return FALSE;
  51.  
  52.     //Get the interface, which calls AddRef
  53.     hr=pRE->lpVtbl->QueryInterface((PENUMRECT)pRE, &IID_IEnumRECT
  54.         , (void **)ppEnum);
  55.     return SUCCEEDED(hr);
  56.     }
  57.  
  58.  
  59.  
  60.  
  61.  
  62. /*
  63.  * RECTENUM_Constructor
  64.  *
  65.  * Purpose:
  66.  *  Constructor for an IMPIEnumRect structure
  67.  *
  68.  * Parameters:
  69.  *  None
  70.  */
  71.  
  72. PRECTENUMERATOR RECTENUM_Constructor(void)
  73.     {
  74.     PRECTENUMERATOR     pRE;
  75.     UINT                i;
  76.  
  77.     /*
  78.      * First time through initialize function table.  Such a table
  79.      * could be defined as a constant instead of doing explicit
  80.      * initialization here.  However, this method shows exactly
  81.      * which pointers are going where and does not depend on knowing
  82.      * the ordering of the functions in the table, just the names.
  83.      */
  84.     if (!g_fVtblInitialized)
  85.         {
  86.         vtEnumRect.QueryInterface=RECTENUM_QueryInterface;
  87.         vtEnumRect.AddRef        =RECTENUM_AddRef;
  88.         vtEnumRect.Release       =RECTENUM_Release;
  89.         vtEnumRect.Next          =RECTENUM_Next;
  90.         vtEnumRect.Skip          =RECTENUM_Skip;
  91.         vtEnumRect.Reset         =RECTENUM_Reset;
  92.         vtEnumRect.Clone         =RECTENUM_Clone;
  93.  
  94.         g_fVtblInitialized=TRUE;
  95.         }
  96.  
  97.     pRE=(PRECTENUMERATOR)malloc(sizeof(RECTENUMERATOR));
  98.  
  99.     if (NULL==pRE)
  100.         return NULL;
  101.  
  102.     //Initialize function table pointer
  103.     pRE->lpVtbl=&vtEnumRect;
  104.  
  105.     //Initialize the array of rectangles
  106.     for (i=0; i < CRECTS; i++)
  107.         SetRect(&pRE->m_rgrc[i], i, i*2, i*3, i*4);
  108.  
  109.     //Ref counts always start at zero
  110.     pRE->m_cRef=0;
  111.  
  112.     //Current pointer is the first element.
  113.     pRE->m_iCur=0;
  114.  
  115.     return pRE;
  116.     }
  117.  
  118.  
  119.  
  120.  
  121.  
  122. /*
  123.  * RECTENUM_Destructor
  124.  *
  125.  * Purpose:
  126.  *  Destructor for RECTENUMERATOR structures.
  127.  *
  128.  * Parameters:
  129.  *  pRE            PRECTENUMERATOR to free
  130.  */
  131.  
  132. void RECTENUM_Destructor(PRECTENUMERATOR pRE)
  133.     {
  134.     if (NULL==pRE)
  135.         return;
  136.  
  137.     free(pRE);
  138.     return;
  139.     }
  140.  
  141.  
  142.  
  143.  
  144. /*
  145.  * RECTENUM_QueryInterface
  146.  *
  147.  * Purpose:
  148.  *  Manages interfaces for the RECTENUMERATOR object.
  149.  *
  150.  * Parameters:
  151.  *  pEnum           PENUMRECT to affect
  152.  *  riid            REFIID of the interface to return.
  153.  *  ppv             PPVOID in which to return the pointer.
  154.  *
  155.  * Return Value:
  156.  *  HRESULT         NOERROR if successful, E_NOINTERFACE if the
  157.  *                  interface is not supported.
  158.  */
  159.  
  160. STDMETHODIMP RECTENUM_QueryInterface(PENUMRECT pEnum
  161.     , REFIID riid, PPVOID ppv)
  162.     {
  163.     //Always NULL the out-parameters
  164.     *ppv=NULL;
  165.  
  166.     if (IsEqualIID(riid, &IID_IUnknown)
  167.         || IsEqualIID(riid, &IID_IEnumRECT))
  168.         *ppv=pEnum;
  169.  
  170.     if (NULL==*ppv)
  171.         return ResultFromScode(E_NOINTERFACE);
  172.  
  173.     //AddRef any interface we'll return.
  174.     ((LPUNKNOWN)*ppv)->lpVtbl->AddRef((LPUNKNOWN)*ppv);
  175.     return NOERROR;
  176.     }
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184. /*
  185.  * RECTENUM_AddRef
  186.  *
  187.  * Purpose:
  188.  *  Increments the reference count on the object.
  189.  *
  190.  * Parameters:
  191.  *  pEnum           PENUMRECT to affect
  192.  *
  193.  * Return Value:
  194.  *  ULONG           New reference count.
  195.  */
  196.  
  197. STDMETHODIMP_(ULONG) RECTENUM_AddRef(PENUMRECT pEnum)
  198.     {
  199.     PRECTENUMERATOR       pRE=(PRECTENUMERATOR)pEnum;
  200.  
  201.     return ++pRE->m_cRef;
  202.     }
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209. /*
  210.  * RECTENUM_Release
  211.  *
  212.  * Purpose:
  213.  *  Indicates that someone on whose behalf we once AddRef'd has
  214.  *  finished with the object.  We decrement our reference count
  215.  *  and if zero, we delete the object.
  216.  *
  217.  * Parameters:
  218.  *  pEnum           PENUMRECT to affect
  219.  *
  220.  * Return Value:
  221.  *  ULONG           Current reference count after decrement.  If
  222.  *                  this returns zero then the interface is no
  223.  *                  longer valid.
  224.  */
  225.  
  226. STDMETHODIMP_(ULONG) RECTENUM_Release(PENUMRECT pEnum)
  227.     {
  228.     PRECTENUMERATOR       pRE=(PRECTENUMERATOR)pEnum;
  229.  
  230.     if (0!=--pRE->m_cRef)
  231.         return pRE->m_cRef;
  232.  
  233.     RECTENUM_Destructor(pRE);
  234.     return 0;
  235.     }
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242.  
  243. /*
  244.  * RECTENUM_Next
  245.  *
  246.  * Purpose:
  247.  *  Returns the next rectangle in the enumerator.
  248.  *
  249.  * Parameters:
  250.  *  pEnum           PENUMRECT to affect
  251.  *  cRect           DWORD number of RECTs to return
  252.  *  prc             LPRECT in which to store the returned RECT.
  253.  *  pdwRects        LPDWORD in which to store the number of
  254.  *                  structs returned.
  255.  *
  256.  * Return Value:
  257.  *  HRESULT         NOERROR if successful, S_FALSE otherwise,
  258.  */
  259.  
  260. STDMETHODIMP RECTENUM_Next(PENUMRECT pEnum, DWORD cRect, LPRECT prc
  261.     , LPDWORD pdwRects)
  262.     {
  263.     PRECTENUMERATOR     pRE=(PRECTENUMERATOR)pEnum;
  264.     DWORD               cRectReturn=0L;
  265.  
  266.     if (NULL==pdwRects)
  267.         {
  268.         if (1L!=cRect)
  269.             return ResultFromScode(S_FALSE);
  270.         }
  271.     else
  272.         *pdwRects=0L;
  273.  
  274.     if (NULL==prc || (pRE->m_iCur >= CRECTS))
  275.         return ResultFromScode(S_FALSE);
  276.  
  277.     while (pRE->m_iCur < CRECTS && cRect > 0)
  278.         {
  279.         *prc++=pRE->m_rgrc[pRE->m_iCur++];
  280.         cRectReturn++;
  281.         cRect--;
  282.         }
  283.  
  284.     if (NULL!=pdwRects)
  285.         *pdwRects=cRectReturn;
  286.  
  287.     return NOERROR;
  288.     }
  289.  
  290.  
  291.  
  292.  
  293.  
  294. /*
  295.  * RECTENUM_Skip
  296.  *
  297.  * Purpose:
  298.  *  Skips the next n elements in the enumerator.
  299.  *
  300.  * Parameters:
  301.  *  pEnum           PENUMRECT to affect
  302.  *  cSkip           DWORD number of elements to skip.
  303.  *
  304.  * Return Value:
  305.  *  HRESULT         NOERROR if successful, S_FALSE if we could not
  306.  *                  skip the requested number.
  307.  */
  308.  
  309. STDMETHODIMP RECTENUM_Skip(PENUMRECT pEnum, DWORD cSkip)
  310.     {
  311.     PRECTENUMERATOR     pRE=(PRECTENUMERATOR)pEnum;
  312.  
  313.     if ((pRE->m_iCur+cSkip) >= CRECTS)
  314.         return ResultFromScode(S_FALSE);
  315.  
  316.     pRE->m_iCur+=cSkip;
  317.     return NOERROR;
  318.     }
  319.  
  320.  
  321.  
  322.  
  323.  
  324. /*
  325.  * RECTENUM_Reset
  326.  *
  327.  * Purpose:
  328.  *  Resets the current element in the enumerator to zero.
  329.  *
  330.  * Parameters:
  331.  *  pEnum           PENUMRECT to affect
  332.  *
  333.  * Return Value:
  334.  *  HRESULT         NOERROR
  335.  */
  336.  
  337. STDMETHODIMP RECTENUM_Reset(PENUMRECT pEnum)
  338.     {
  339.     PRECTENUMERATOR     pRE=(PRECTENUMERATOR)pEnum;
  340.  
  341.     pRE->m_iCur=0;
  342.     return NOERROR;
  343.     }
  344.  
  345.  
  346.  
  347.  
  348. /*
  349.  * RECTENUM_Clone
  350.  *
  351.  * Purpose:
  352.  *  Creates a copy enumerator.
  353.  *
  354.  * Parameters:
  355.  *  ppEnum          PENUMRECT * in which to store the clone.
  356.  *
  357.  * Return Value:
  358.  *  HRESULT         NOERROR if successful, error code otherwise.
  359.  */
  360.  
  361. STDMETHODIMP RECTENUM_Clone(PENUMRECT pEnum, PENUMRECT *ppEnum)
  362.     {
  363.     PRECTENUMERATOR     pRE=(PRECTENUMERATOR)pEnum;
  364.  
  365.     if (CreateRECTEnumeratorC(ppEnum))
  366.         {
  367.         /*
  368.          * Copy the current index.  The typecast is safe because
  369.          * we know that the IEnumRECT from the creation function
  370.          * is really a RECTENUMERATOR pointer.
  371.          */
  372.         ((PRECTENUMERATOR)(*ppEnum))->m_iCur=pRE->m_iCur;
  373.         return NOERROR;
  374.         }
  375.  
  376.     return ResultFromScode(E_OUTOFMEMORY);
  377.     }
  378.