Click here to Skip to main content
15,897,334 members
Articles / Programming Languages / C++

Writing Win32 Apps with C++: V2 - part 1

Rate me:
Please Sign up or sign in to vote.
4.70/5 (34 votes)
20 Jun 2005CPOL14 min read 108K   1.2K   73  
An independent framework to handle Win32 objects inside C++ classes.
//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)

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
Italy Italy
Born and living in Milan (Italy), I'm an engineer in electronics actually working in the ICT department of an important oil/gas & energy company as responsible for planning and engineering of ICT infrastructures.
Interested in programming since the '70s, today I still define architectures for the ICT, deploying dedicated specific client application for engineering purposes, working with C++, MFC, STL, and recently also C# and D.

Comments and Discussions