//wndmsg.h
// message crackers
#pragma once
namespace GE_{ namespace win{
struct ID_generator
{
//generates a different integer on every call
static UINT NewID() { static UINT n = 23000; return n++; }
};
template<class Type>
struct Typed_id
{
//associate an integer to a type
static UINT ID() { static UINT n=0; if(!n) n = ID_generator::NewID(); return n; }
};
//Typedmassages: an data struct adaped to become a WM_NOTIFY
//
template<class T>
struct TypedMessage:
public NMHDR,
public T
{
static ID() {return Typed_id<T>::ID();}
LRESULT Send(HWND _hwnd, UINT _nID, HWND _hwndFrom)
{
hwndFrom = _hwndFrom;
idFrom = _nID;
code = ID();
return SendMessage(_hwnd, WM_NOTIFY, _nID, (LPARAM)this );
}
};
struct forwardmessage
{
windowmessage* p_msg;
UINT mapID;
_window::nexter* p_nexter;
};
typedef TypedMessage<forwardmessage> M_Forward;
}}
// Cracking macros
#ifdef GE_BEGIN_MSG_MAP
#undef GE_BEGIN_MSG_MAP
#undef GE_ALT_MSG_MAP
#undef GE_END_MSG_MAP
#endif
// BEGIN, ALT and END masg map use the same ATL mechanism
#define GE_BEGIN_MSG_MAP(classname)\
virtual bool on_message(GE_::win::windowmessage* _pmsg, UINT _mapID, nexter& _nexter)\
{\
bool filtered = false;\
switch(_mapID)\
{\
case 0:
#define GE_ALT_MSG_MAP(_mapID)\
break;\
case _mapID:\
#define GE_END_MSG_MAP()\
break;\
}\
return false;\
}
/// generic message crakers:
// use filter, typecasts and invoke a member function
// prototype: bool memebrfunc(parameters, ..., LRESULT& _res, nexter& _nexter)
#define GE_ON(flt, func)\
if(flt && func(_pmsg->lResult, _nexter)) return true;
#define GE_ON_W(flt, func, wType)\
if(flt && func((wType)_pmsg->wParam, _pmsg->lResult, _nexter)) return true;
#define GE_ON_WW(flt, func, wTypeL, wTypeH)\
if(flt && func((wTypeL)_pmsg->wParamLo(), (wTypeh)_pmsg->wParamHi(), _pmsg->lResult, _nexter)) return true;
#define GE_ON_L(flt, func, lType)\
if(flt && func((lType)_pmsg->lParam, _pmsg->lResult, _nexter)) return true;
#define GE_ON_LL(flt, func, lTypeL, lTypeH)\
if(flt && func((lTypeL)_pmsg->lParamLo(), (lTypeh)_pmsg->lParamHi(), _pmsg->lResult, _nexter)) return true;
#define GE_ON_WL(flt, func, wType, lType)\
if(flt && func((wType)_pmsg->wParam, (lType)_pmsg->lParam, _pmsg->lResult, _nexter)) return true;
#define GE_ON_WWL(flt, func, wTypeL, wTypeH, lType)\
if(flt && func((wTypeL)_pmsg->wParamLo(), (wTypeH)_pmsg->wParamHi(), (lType)_pmsg->lParam, _pmsg->lResult, _nexter)) return true;
#define GE_ON_WLL(flt, func, wType, lTypeL, lTypeH)\
if(flt && func((wType)_pmsg->wParam, (lTypeL)_pmsg->lParamLo(), (lTypeH)_pmsg->lParamHi(), _pmsg->lResult, _nexter)) return true;
#define GE_ON_WWLL(flt, func, wTypeL, wTypeH, lTypeL, lTypeH)\
if(flt && func((wTypeL)_pmsg->wParamLo(), (wTypeH)_pmsg->wParamHi(), (lTypeL)_pmsg->lParamLo(), (lTypeH)_pmsg->lParamHi(), _pmsg->lResult, _nexter)) return true;
#define GE_ON_M(flt, func)\
if(flt && func(*_pmsg, _nexter)) return true;
// special cracker to forward messages
#define GE_DO_ROUTE(flt, pmsgmap, idmap)\
if(flt && (pmsgmap) && (pmsgmap)->on_message(_pmsg, idmap, _nexter)) return true;
#define GE_DO_BROADCAST(flt, first, last, idmap)\
if(flt) \
for(;first!=last;first++) \
if((*first)->on_message(_pmsg, idmap, _nexter)) \
return true; \
return false;
#define GE_DO_CHAIN(flt, classname, idmap)\
if(flt && classname::on_message(_pmsg, idmap, _nexter)) return true;
#define GE_DO_RESEND(flt, hwnd, ret)\
if(flt) { _pmsg->lResult = SendMessage(hwnd, _pmsg->uMsg, _pmsg->wParam, _pmsg->lParam); if(ret)return true;}
#define GE_DO_FWD(flt, hwnd, tag, ret)\
if(flt)\
{\
GE_::win::M_Forward fwd; fwd.p_msg = _pmsg; fwd.mapID = tag; fwd.p_nexter = _nexter\
_pmsg->lResult = fwd.Send(hwnd, tag, *this); if(ret)return true;\
}
#define GE_ON_FWD(tag, map)\
if(_pmsg->uMsg == WM_NOTIFY && _pmsg->nmhdr().code == GE_::win::M_Forward::ID() && _pmsg->wParam == tag)\
return on_message(*((GE_::win::M_Forward*)&_pmsg->nmhdr()).p_msg, map, _nexter);
#define GE_DO_SEND_CHILDREN(flt, ret)\
if(flt)\
{\
for(HWND hChild = GetWindow(_pmsg->hwnd, GW_CHILD); hChild; hChild = GetWindow(hChild, GW_HWNDNEXT))\
SendMessage(hChild, _pmsg->hwnd, _pmsg->wParam, _pmsg->lParam);\
if(ret) return true; \
}
#define GE_DO_FWD_CHILDREN(flt, tag, ret)\
if(flt) \
{\
for(HWND hChild = GetWindow(_pmsg->hwnd, GW_CHILD); hChild; hChild = GetWindow(hChild, GW_HWNDNEXT))\
GE_DO_FWD(true, hChild, tag, true);\
if(ret) return true;\
}
// filters (use as the "flt" parameter on previous macros)
#define GE_MSG(msg) (_pmsg->uMsg == msg)
#define GE_MSG_W(msg, id) (_pmsg->uMsg == msg && _pmsg->wParam == id)
#define GE_MSG_W_RANGE(msg, id1, id2) (_pmsg->uMsg == msg && _pmsg->wParam >= id1 && _pmsg->wParam <= id2)
#define GE_MSG_WL(msg, id) (_pmsg->uMsg == msg && _pmsg->wParamLo() == id)
#define GE_MSG_WL_RANGE(msg, id1, id2) (_pmsg->uMsg == msg && _pmsg->wParamLo() >= id1 && _pmsg->wParamLo() <= id2)
#define GE_MSG_NM_ID(msg, id) (_pmsg->uMsg == msg && _pmsg->wParam == id)
#define GE_MSG_NM_CODE(msg, nmcode) (_pmsg->uMsg == msg && _pmsg->nmhdr().code == nmcode)
#define GE_MSG_NM_RANGE(msg, id1, id2) (_pmsg->uMsg == msg && _pmsg->wParam >= id1 && _pmsg->wParam <= id2)
#define GE_MSG_NM_ID_CODE(msg, id,nmcode) (_pmsg->uMsg == msg && _pmsg->wParam == id && _pmsg->nmhdr().code == nmcode)
#define GE_MSG_NM_RANGE_CODE(msg, id1,id2,nmcode) (_pmsg->uMsg == msg && _pmsg->wParam >= id1 && _pmsg->wParam<=id2 && _pmsg->nmhdr().code == nmcode)
#define GE_CONTROL(id,nmcode) GE_MSG_W(WM_COMMAND, MAKELONG(id,nmcode))
#define GE_CONTROL_RANGE(id1, id2, nmcode) GE_MSG_W_RANGE(WM_COMMAND, MAKELONG(id1,nmcode), MAKELONG(id2,nmcode))
#define GE_COMMAND(id) (GE_CONTROL(id,0)||GE_CONTROL(id,1))
#define GE_COMMAND_RANGE(id1, id2) (GE_CONTROL_RANGE(id1,id2,0)||GE_CONTROL_RANGE(id1,id2,1))
#define GE_NOTIFY_ID(id) GE_MSG_NM_ID(WM_NOTIFY, id)
#define GE_NOTIFY_CODE(nmcode) GE_MSG_NM_CODE(WM_NOTIFY, nmcode)
#define GE_NOTIFY_RANGE(id1, id2) GE_MSG_NM_RANGE(WM_NOTIFY, id1, id2)
#define GE_NOTIFY_ID_CODE(id,nmcode) GE_MSG_NM_ID_CODE(WM_NOTIFY, id, nmcode)
#define GE_NOTIFY_RANGE_CODE(id1,id2,nmcode) GE_MSG_NM_RANGE_CODE(WM_NOTIFY, id1, id2, nmcode)