void * parm
added for my use. (I suppose I should add at this point that Keith pointed
this idea out; I just implemented it... And strictly speaking, this isn't a GL
trick, just a C++ trick that seemed kinda slick.)The GL-related problem was this:
I needed to call GetFeatureInfo() to get access to a user-defined
display type, (i.e. 3584-4095, or 0x0E00-0x0FFF, as defined in the GPVF 1.0
doc). Inside CVMap::GetFeatureInfo(), if it's determined that the
requested DT has a base type of "other", then GetOtherInfoHook()
gets called.
GetOtherInfoHook() is a virtual function defined in
CMap, whose default behavior is to do nothing. I derived
CSAVMapLocal from CVMapLocal, which is in turn
derived from CVMap. I was then able to override
GetOtherInfoHook(), and get called with pointers to the user and
text data for that grid.
The problem, then, was that I needed to pass other info along into
GetOtherInfoHook(). Since I was searching for a given item in the
grid, I needed to pass in the search term.
My first thought was to use a global variable. It would need to be visible to
the calling code, which was in a separate source file from the
CSAVMapLocal code. It would have worked, but globals are
decidedly unelegant.
In the world of Windows programming, and actually in the straight C programming
world as well, a commonly accepted way of doing this would be for
GetFeatureInfo() to provide a void pointer to the caller, who
would then pack up his data into a struct (or class) and pass it along with the
other parms. GetFeatureInfo() would then treat it as a little
black box, and simply pass it along to any call to
GetOtherInfoHook() and any other hooks it provides. At this
point, I took this idea to Keith, who, true to form, would have preferred
walking over hot coals to changing the GL3.0 API, even to add a parm with a
default value. (And as mentioned above, proceeded to provide the following
idea, which worked quite nicely.)
The solution was this: Since I already had a CVMap-derived class,
I would add another version of GetFeatureInfo() that would include
a parm for my pointer. I would also add the pointer as a member of my derived
class. My new GetFeatureInfo() function would do nothing more
than set this pointer and call CVMap::GetFeatureInfo() as usual.
When CVMap::GetFeatureInfo() gets around to calling
GetOtherInfoHook(), GetOtherInfoHook() can reference
the pointer as if it was a part of CVMap. And indeed, at this
point, the pointer is a part of my
CVMap, which is CSAVMapLocal.
As you'll see below, there is one other concern here. In CMap and
CVMap, our base classes, GetFeatureInfo is virtual.
The first task is to add the new function, with the extra parameter, which sets
the pointer and calls the base class method. This works fine, but breaks any
calls to the old, four-parm version of GetFeatureInfo(). So we
add a second, virtual, four-parm version of GetFeatureInfo() that
simply calls the base class method.
The relevant parts of CMap, CVMap,
CVMapLocal and CSAVMapLocal are shown below:
class CLASSEXPORT CMap
{
.
.
.
public:
virtual GLBOOL GetFeatureInfo(const SFeatureHandle& stFH,
SFeatureInfo* pstFI, L_POINT* plptShapePoints,
void* pOther);
protected:
//This function is called by GetFeatureInfo for user-type DTs
virtual GLBOOL GetOtherInfoHook(uSHORT usDT, void* pUserData,
uSHORT usUserDataSize, char* pszTextData);
.
.
.
}; //CMap
class CVMap : public CMap
{
.
.
.
public:
// Same as in CMap [DWJ]
virtual GLBOOL GetFeatureInfo(const SFeatureHandle& stFH,
SFeatureInfo* pstFI, L_POINT* plptShapePoints,
void* pOther);
.
.
.
}; //CVMap
class CLASSEXPORT CVMapLocal : public CVMap
{
.
.
.
}; //CVMapLocal
class CLASSEXPORT CSAVMapLocal : public CVMapLocal
{
protected:
void *m_pUserHookPtr;
.
.
.
//This function is called by GetFeatureInfo for user-type DTs
virtual GLBOOL GetOtherInfoHook( uSHORT usDT,
void *pUserData,
uSHORT usUserDataSize,
char *pszTextData );
public:
inline virtual GLBOOL GetFeatureInfo( const SFeatureHandle &stFH,
SFeatureInfo *pstFI,
L_POINT *plptShapePoints,
void *pOther )
{
return ( CVMapLocal::GetFeatureInfo( stFH, pstFI, plptShapePoints,
pOther ) );
}
inline GLBOOL GetFeatureInfo( const SFeatureHandle &stFH,
void *pUserHookPtr,
SFeatureInfo *pstFI,
L_POINT *plptShapePoints,
void *pOther )
{
m_pUserHookPtr = pUserHookPtr;
return ( CVMapLocal::GetFeatureInfo( stFH, pstFI, plptShapePoints,
pOther ) );
m_pUserHookPtr = NULL;
}
.
.
.
};
CSAVMapLocal::CSAVMapLocal()
: CVMapLocal()
{
.
.
.
m_pUserHookPtr = NULL;
.
.
.
}