ENUMC.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:8k
源码类别:

Windows编程

开发平台:

Visual C++

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