The EnumRect Sample

As additional proof that OLE has a language-independent binary standard, the EnumRect sample (CHAP02\ENUMRECT) implements identical enumerators for RECT structures in C and C++ but uses both of them from exactly the same C++ client code. The enumerators themselves implement an interface named IEnumRECT, which is defined for this sample and is not a standard OLE interface. The sample file IENUM.H contains the C and C++ definitions, using the STDMETHOD macros that expand to the appropriate calling conversion:


//C++ definition of an interface
#ifdef __cplusplus

typedef struct IEnumRECT IEnumRECT;
typedef IEnumRECT *PENUMRECT;

struct IEnumRECT
{
STDMETHOD(QueryInterface)(REFIID, PPVOID)=0;
STDMETHOD_(ULONG,AddRef)(void)=0;
STDMETHOD_(ULONG,Release)(void)=0;
STDMETHOD(Next)(DWORD, LPRECT, LPDWORD)=0;
STDMETHOD(Skip)(DWORD)=0;
STDMETHOD(Reset)(void)=0;
STDMETHOD(Clone)(PENUMRECT *)=0;
};

#else //!__cplusplus

typedef struct
{
struct IEnumRECTVtbl FAR *lpVtbl;
} IEnumRECT, *PENUMRECT;

typedef struct IEnumRECTVtbl IEnumRECTVtbl;

struct IEnumRECTVtbl
{
STDMETHOD(QueryInterface)(PENUMRECT, REFIID, PPVOID);
STDMETHOD_(ULONG, AddRef)(PENUMRECT);
STDMETHOD_(ULONG, Release)(PENUMRECT);
STDMETHOD(Next)(PENUMRECT, DWORD, LPRECT, LPDWORD);
STDMETHOD(Skip)(PENUMRECT, DWORD);
STDMETHOD(Reset)(PENUMRECT);
STDMETHOD(Clone)(PENUMRECT, PENUMRECT *);
};

#endif //!__cplusplus

For convenience, we'll call the object that implements this interface a RectEnumerator. The part of EnumRect that is the client displays a small window with a menu that allows you to create either a C or a C++ object. There are two API-type functions that EnumRect calls to create the objects: CreateRectEnumeratorC and CreateRectEnumeratorCPP. These are typical functions that create an object and return an interface pointer that must later be released, as usual. Regardless of which object you create, you can use the other menu items in EnumRect to call the various IEnumRECT member functions. EnumRect displays only the mundane results of the function (success or failure) in its client area, so it's most enlightening to run this sample in a debugger to step through the code and watch what happens when calls are made.

Note that IID_IEnumRECT is defined in INC\BOOKGUID.H, which is pulled in through EnumRect's inclusion of INC\INOLE.H. The ENUMRECT.CPP file defines the INITGUIDS symbol to include this IID in the compilation.