ENUMCPP.CPP

/* 
* ENUMCPP.CPP
* Enumerator in C++ Chapter 2
*
* Implements the CEnumRECT class
*
* Copyright (c)1993-1995 Microsoft Corporation, All Rights Reserved
*
* Kraig Brockschmidt, Microsoft
* Internet : kraigb@microsoft.com
* Compuserve: >INTERNET:kraigb@microsoft.com
*/


#include "enumrect.h"


/*
* CreateRECTEnumeratorCPP
*
* Purpose:
* Creates an enumerator object returning an IEnumRECT interface.
*
* Parameters:
* ppEnum PENUMRECT * in which to return the
* interface pointer on the created object.
*
* Return Value:
* BOOL TRUE if the function is successful,
* FALSE otherwise.
*/

BOOL CreateRECTEnumeratorCPP(PENUMRECT *ppEnum)
{
PCEnumRect pER;
HRESULT hr;

if (NULL==ppEnum)
return FALSE;

//Create the object
pER=new CEnumRect();

if (NULL==pER)
return FALSE;

//Get the interface, which calls AddRef
hr=pER->QueryInterface(IID_IEnumRECT, (void **)ppEnum);
return SUCCEEDED(hr);
}





/*
* CEnumRect::CEnumRect
* CEnumRect::~CEnumRect
*
* Constructor Parameters:
* None
*/

CEnumRect::CEnumRect(void)
{
UINT i;

//Initialize the array of rectangles
for (i=0; i < CRECTS; i++)
SetRect(&m_rgrc[i], i, i*2, i*3, i*4);

//Ref counts always start at zero
m_cRef=0;

//Current pointer is the first element.
m_iCur=0;

return;
}


CEnumRect::~CEnumRect(void)
{
return;
}




/*
* CEnumRect::QueryInterface
*
* Purpose:
* Manages interfaces for the CEnumRect object.
*
* Parameters:
* riid REFIID of the interface to return.
* ppv PPVOID in which to return the pointer.
*
* Return Value:
* HRESULT NOERROR if successful, E_NOINTERFACE if the
* interface is not supported.
*/

STDMETHODIMP CEnumRect::QueryInterface(REFIID riid, PPVOID ppv)
{
//Always NULL the out-parameters
*ppv=NULL;

/*
* No explicit typecast necessary since we singly derive
* from IEnumRECT.
*/
if (IID_IUnknown==riid || IID_IEnumRECT==riid)
*ppv=this;

if (NULL==*ppv)
return ResultFromScode(E_NOINTERFACE);

//AddRef any interface we'll return.
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}




/*
* CEnumRect::AddRef
*
* Purpose:
* Increments the reference count on the object.
*
* Parameters:
* None
*
* Return Value:
* ULONG New reference count.
*/

STDMETHODIMP_(ULONG) CEnumRect::AddRef(void)
{
return ++m_cRef;
}






/*
* CEnumRect::Release
*
* Purpose:
* Indicates that someone on whose behalf we once AddRef'd has
* finished with the object. We decrement our reference count
* and if zero, we delete the object.
*
* Parameters:
* None
*
* Return Value:
* ULONG Current reference count after decrement. If
* this returns zero then the interface is no
* longer valid.
*/

STDMETHODIMP_(ULONG) CEnumRect::Release(void)
{
if (0!=--m_cRef)
return m_cRef;

delete this;
return 0;
}







/*
* CEnumRect::Next
*
* Purpose:
* Returns the next rectangle in the enumerator.
*
* Parameters:
* cRect DWORD number of RECTs to return
* prc LPRECT in which to store the returned RECT.
* pdwRects LPDWORD in which to store the number of
* structs returned.
*
* Return Value:
* HRESULT NOERROR if successful, S_FALSE otherwise,
*/

STDMETHODIMP CEnumRect::Next(DWORD cRect, LPRECT prc, LPDWORD pdwRects)
{
DWORD cRectReturn=0L;

if (NULL==pdwRects)
{
if (1L!=cRect)
return ResultFromScode(S_FALSE);
}
else
*pdwRects=0L;

if (NULL==prc || (m_iCur >= CRECTS))
return ResultFromScode(S_FALSE);

while (m_iCur < CRECTS && cRect > 0)
{
*prc++=m_rgrc[m_iCur++];
cRectReturn++;
cRect--;
}

if (NULL!=pdwRects)
*pdwRects=cRectReturn;

return NOERROR;
}





/*
* CEnumRect::Skip
*
* Purpose:
* Skips the next n elements in the enumerator.
*
* Parameters:
* cSkip DWORD number of elements to skip.
*
* Return Value:
* HRESULT NOERROR if successful, S_FALSE if we could not
* skip the requested number.
*/

STDMETHODIMP CEnumRect::Skip(DWORD cSkip)
{
if ((m_iCur+cSkip) >= CRECTS)
return ResultFromScode(S_FALSE);

m_iCur+=cSkip;
return NOERROR;
}




/*
* CEnumRect::Reset
*
* Purpose:
* Resets the current element in the enumerator to zero.
*
* Parameters:
* None
*
* Return Value:
* HRESULT NOERROR
*/

STDMETHODIMP CEnumRect::Reset(void)
{
m_iCur=0;
return NOERROR;
}




/*
* CImpEnumRECT::Clone
*
* Purpose:
* Creates a copy enumerator.
*
* Parameters:
* ppEnum PENUMRECT * in which to store the clone.
*
* Return Value:
* HRESULT NOERROR if successful, error code otherwise.
*/

STDMETHODIMP CEnumRect::Clone(PENUMRECT *ppEnum)
{
if (CreateRECTEnumeratorCPP(ppEnum))
{
/*
* Copy the current index. The typecast is safe because
* we know that the IEnumRECT from the creation function
* is really a CEnumRect pointer.
*/
((PCEnumRect)(*ppEnum))->m_iCur=m_iCur;
return NOERROR;
}

return ResultFromScode(E_OUTOFMEMORY);
}