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 / chap12 / datatran / ienumfe.cpp < prev    next >
C/C++ Source or Header  |  1995-05-03  |  6KB  |  275 lines

  1. /*
  2.  * IENUMFE.CPP
  3.  * Data Tranfer Object for Chapter 12
  4.  *
  5.  * IEnumFORMATETC implementation specifically for the Data Tranfer
  6.  * objects.  This enumerator copies the state of the data list in
  7.  * the data object and uses that to maintain what FORMATETCs it
  8.  * knows.
  9.  *
  10.  * Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
  11.  *
  12.  * Kraig Brockschmidt, Microsoft
  13.  * Internet  :  kraigb@microsoft.com
  14.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  15.  */
  16.  
  17.  
  18. #include "dataobj.h"
  19.  
  20.  
  21. extern HINSTANCE g_hInst;
  22.  
  23.  
  24. /*
  25.  * CEnumFormatEtc::CEnumFormatEtc
  26.  * CEnumFormatEtc::~CEnumFormatEtc
  27.  *
  28.  * Parameters (Constructor):
  29.  *  pUnkRef         LPUNKNOWN to use for reference counting.
  30.  */
  31.  
  32. CEnumFormatEtc::CEnumFormatEtc(LPUNKNOWN pUnkRef)
  33.     {
  34.     m_cRef=0;
  35.     m_pUnkRef=pUnkRef;
  36.     m_iCur=0;
  37.     m_cItems=0;
  38.     return;
  39.     }
  40.  
  41.  
  42. CEnumFormatEtc::~CEnumFormatEtc(void)
  43.     {
  44.     if (NULL!=m_prgfe)
  45.         {
  46.         LPMALLOC    pIMalloc;
  47.  
  48.         if (SUCCEEDED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  49.             {
  50.             pIMalloc->Free(m_prgfe);
  51.             pIMalloc->Release();
  52.             }
  53.         }
  54.  
  55.     return;
  56.     }
  57.  
  58.  
  59.  
  60. /*
  61.  * CEnumFormatEtc::Init
  62.  *
  63.  * Purpose:
  64.  *  Copies the FORMATETCs in the data object's listbox into our
  65.  *  own, that is, we make a snapshot for this enumerator.
  66.  *
  67.  * Parameters:
  68.  *  hList           HWND of the listbox containing RENDERINGs
  69.  *
  70.  * Return Value:
  71.  *  BOOL            TRUE if initialization worked,
  72.  *                  FALSE otherwise.
  73.  */
  74. BOOL CEnumFormatEtc::Init(HWND hList)
  75.     {
  76.     UINT        i, cItems;
  77.     LPMALLOC    pIMalloc;
  78.     PRENDERING  pRen;
  79.     LPFORMATETC pFE;
  80.     DWORD       cb;
  81.  
  82.     if (NULL==hList)
  83.         return FALSE;
  84.  
  85.     cItems=(UINT)SendMessage(hList, LB_GETCOUNT, 0, 0L);
  86.  
  87.     if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  88.         return FALSE;
  89.  
  90.     m_prgfe=(LPFORMATETC)pIMalloc->Alloc(cItems*sizeof(FORMATETC));
  91.     pIMalloc->Release();
  92.  
  93.     if (NULL!=m_prgfe)
  94.         {
  95.         pFE=m_prgfe;
  96.  
  97.         for (i=0; i < cItems; i++)
  98.             {
  99.             cb=SendMessage(hList, LB_GETTEXT, i, (LPARAM)&pRen);
  100.  
  101.             if (LB_ERR!=cb)
  102.                 {
  103.                 //Copy just the FORMATETC
  104.                 *pFE++=pRen->fe;
  105.                 m_cItems++;
  106.                 }
  107.             }
  108.         }
  109.  
  110.     return TRUE;
  111.     }
  112.  
  113.  
  114.  
  115. /*
  116.  * CEnumFormatEtc::QueryInterface
  117.  * CEnumFormatEtc::AddRef
  118.  * CEnumFormatEtc::Release
  119.  *
  120.  * Purpose:
  121.  *  IUnknown members for CEnumFormatEtc object.  For QueryInterface
  122.  *  we only return out own interfaces and not those of the data
  123.  *  object.  However, since enumerating formats only makes sense
  124.  *  when the data object is around, we insure that it stays as
  125.  *  long as we stay by calling an outer IUnknown for AddRef and
  126.  *  Release.  But since we are not controlled by the lifetime of
  127.  *  the outer object, we still keep our own reference count in
  128.  *  order to free ourselves.
  129.  */
  130.  
  131. STDMETHODIMP CEnumFormatEtc::QueryInterface(REFIID riid, PPVOID ppv)
  132.     {
  133.     *ppv=NULL;
  134.  
  135.     /*
  136.      * Enumerators are separate objects, not the data object, so
  137.      * we only need to support out IUnknown and IEnumFORMATETC
  138.      * interfaces here with no concern for aggregation.
  139.      */
  140.     if (IID_IUnknown==riid || IID_IEnumFORMATETC==riid)
  141.         *ppv=this;
  142.  
  143.     if (NULL!=*ppv)
  144.         {
  145.         ((LPUNKNOWN)*ppv)->AddRef();
  146.         return NOERROR;
  147.         }
  148.  
  149.     return ResultFromScode(E_NOINTERFACE);
  150.     }
  151.  
  152.  
  153. STDMETHODIMP_(ULONG) CEnumFormatEtc::AddRef(void)
  154.     {
  155.     ++m_cRef;
  156.     m_pUnkRef->AddRef();
  157.     return m_cRef;
  158.     }
  159.  
  160. STDMETHODIMP_(ULONG) CEnumFormatEtc::Release(void)
  161.     {
  162.     m_pUnkRef->Release();
  163.  
  164.     if (0!=--m_cRef)
  165.         return m_cRef;
  166.  
  167.     delete this;
  168.     return 0;
  169.     }
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177. /*
  178.  * CEnumFormatEtc::Next
  179.  * CEnumFormatEtc::Skip
  180.  * CEnumFormatEtc::Reset
  181.  * CEnumFormatEtc::Clone
  182.  *
  183.  * Standard enumerator members for IEnumFORMATETC
  184.  */
  185.  
  186. STDMETHODIMP CEnumFormatEtc::Next(ULONG cFE, LPFORMATETC pFE
  187.     , ULONG *pulFE)
  188.     {
  189.     ULONG           cReturn=0L;
  190.  
  191.     if (NULL==m_prgfe)
  192.         return ResultFromScode(S_FALSE);
  193.  
  194.     if (NULL==pulFE)
  195.         {
  196.         if (1L!=cFE)
  197.             return ResultFromScode(E_POINTER);
  198.         }
  199.     else
  200.         *pulFE=0L;
  201.  
  202.     if (NULL==pFE || m_iCur >= m_cItems)
  203.         return ResultFromScode(S_FALSE);
  204.  
  205.     while (m_iCur < m_cItems && cFE > 0)
  206.         {
  207.         *pFE++=m_prgfe[m_iCur++];
  208.         cReturn++;
  209.         cFE--;
  210.         }
  211.  
  212.     if (NULL!=pulFE)
  213.         *pulFE=cReturn;
  214.  
  215.     return NOERROR;
  216.     }
  217.  
  218.  
  219. STDMETHODIMP CEnumFormatEtc::Skip(ULONG cSkip)
  220.     {
  221.     if ((m_iCur+cSkip) >= m_cItems)
  222.         return ResultFromScode(S_FALSE);
  223.  
  224.     m_iCur+=cSkip;
  225.     return NOERROR;
  226.     }
  227.  
  228.  
  229. STDMETHODIMP CEnumFormatEtc::Reset(void)
  230.     {
  231.     m_iCur=0;
  232.     return NOERROR;
  233.     }
  234.  
  235.  
  236. STDMETHODIMP CEnumFormatEtc::Clone(LPENUMFORMATETC *ppEnum)
  237.     {
  238.     PCEnumFormatEtc     pNew;
  239.     LPMALLOC            pIMalloc;
  240.     LPFORMATETC         prgfe;
  241.     BOOL                fRet=TRUE;
  242.     ULONG               cb;
  243.  
  244.     *ppEnum=NULL;
  245.  
  246.     //Copy the memory for the list.
  247.     if (FAILED(CoGetMalloc(MEMCTX_TASK, &pIMalloc)))
  248.         return ResultFromScode(E_OUTOFMEMORY);
  249.  
  250.     cb=m_cItems*sizeof(FORMATETC);
  251.     prgfe=(LPFORMATETC)pIMalloc->Alloc(cb);
  252.  
  253.     if (NULL!=prgfe)
  254.         {
  255.         //Copy the formats
  256.         memcpy(prgfe, m_prgfe, (int)cb);
  257.  
  258.         //Create the clone
  259.         pNew=new CEnumFormatEtc(m_pUnkRef);
  260.  
  261.         if (NULL!=pNew)
  262.             {
  263.             pNew->m_iCur=m_iCur;
  264.             pNew->m_prgfe=prgfe;
  265.             pNew->AddRef();
  266.             fRet=TRUE;
  267.             }
  268.         }
  269.  
  270.     pIMalloc->Release();
  271.  
  272.     *ppEnum=pNew;
  273.     return fRet ? NOERROR : ResultFromScode(E_OUTOFMEMORY);
  274.     }
  275.