#pragma once
#include <wtypes.h>
#include <afxmsg_.h>
class CModule;
typedef BOOL(CModule::*MODULE_PMSG)(LPCONTEXT_HEAD lpContext, LPREQUEST lpRequest);
struct MODULE_MSGMAP_ENTRY
{
UINT nMessage; // windows message
MODULE_PMSG pfn; // routine to call (or special value)
};
struct MODULE_MSGMAP
{
const MODULE_MSGMAP* (PASCAL* pfnGetBaseMap)();
const MODULE_MSGMAP_ENTRY* lpEntries;
};
#define DECLARE_MSG_MAP() \
protected: \
static const MODULE_MSGMAP* PASCAL GetThisMessageMap(); \
virtual const MODULE_MSGMAP* GetMessageMap() const;
#define ON_MSG(message, memberFxn) \
{ message,(MODULE_PMSG)(memberFxn) },
#define BEGIN_MSG_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const MODULE_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const MODULE_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const MODULE_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MSG_MAP() \
{0, (MODULE_PMSG)0 } \
}; \
static const MODULE_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, _messageEntries }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
class CModule
{
DECLARE_MSG_MAP()
public:
CModule();
virtual ~CModule();
BOOL OnRequest(LPCONTEXT_HEAD lpContext, LPREQUEST lpRequest);
};
#include "stdafx.h"
#include "Module.h"
CModule::CModule()
{
}
CModule::~CModule()
{
}
const MODULE_MSGMAP* CModule::GetMessageMap() const
{
return GetThisMessageMap();
}
const MODULE_MSGMAP* CModule::GetThisMessageMap()
{
static const MODULE_MSGMAP_ENTRY _messageEntries[] =
{
{ 0, 0 } // nothing here
};
static const MODULE_MSGMAP messageMap =
{
NULL,
_messageEntries
};
return &messageMap;
}
#ifndef iHashMax
// iHashMax must be a power of two
#define iHashMax 512
#endif
struct MODULE_MSG_CACHE
{
UINT nMsg;
const MODULE_MSGMAP_ENTRY* lpEntry;
const MODULE_MSGMAP* pMessageMap;
};
MODULE_MSG_CACHE _MsgCache[iHashMax] = { 0 };
const MODULE_MSGMAP_ENTRY* FindMessageEntry(const MODULE_MSGMAP_ENTRY* lpEntry, UINT nMsg)
{
while (lpEntry->nMessage != 0)
{
if (lpEntry->nMessage == nMsg)
{
return lpEntry;
}
lpEntry++;
}
return NULL;
}
BOOL CModule::OnRequest(LPCONTEXT_HEAD lpContext, LPREQUEST lpRequest)
{
UINT message = lpRequest->head.nRequest;
const MODULE_MSGMAP* pMessageMap = GetMessageMap();
UINT iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax - 1);
MODULE_MSG_CACHE* pMsgCache = &_MsgCache[iHash];
const MODULE_MSGMAP_ENTRY* lpEntry;
if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
{
lpEntry = pMsgCache->lpEntry;
}
else
{
pMsgCache->nMsg = message;
pMsgCache->pMessageMap = pMessageMap;
for (; pMessageMap->pfnGetBaseMap != NULL;
pMessageMap = (*pMessageMap->pfnGetBaseMap)())
{
// Note: catches BEGIN_MSG_MAP(CMyClass, CMyClass)!
ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
if ((lpEntry = FindMessageEntry(pMessageMap->lpEntries, message)) != NULL)
{
pMsgCache->lpEntry = lpEntry;
break;
}
}
}
if (lpEntry == NULL)
return FALSE;
return (this->*lpEntry->pfn)(lpContext, lpRequest);
}