总结二、MFC消息映射

1、消息映射的现实

// 下面为MFC中定义的一些宏,可自行查看相应的头文件
#ifdef _ATL_ENABLE_PTM_WARNING
#define PTM_WARNING_DISABLE
#define PTM_WARNING_RESTORE
#else
#define PTM_WARNING_DISABLE \
	__pragma(warning( push )) \
	__pragma(warning( disable : 4867 ))
#define PTM_WARNING_RESTORE \
	__pragma(warning( pop ))
#endif //_ATL_ENABLE_PTM_WARNING

// pointer to afx_msg member function
#ifndef AFX_MSG_CALL
#define AFX_MSG_CALL
#endif
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);

// like 'AFX_PMSG' but for CWnd-derived classes only
typedef void (AFX_MSG_CALL CWnd::*AFX_PMSGW)(void);
	
// like 'AFX_PMSG' but for CWinThread-derived classes only
typedef void (AFX_MSG_CALL CWinThread::*AFX_PMSGT)(void);

struct AFX_MSGMAP_ENTRY
{
	UINT nMessage;   // windows message
	UINT nCode;      // control code or WM_NOTIFY code
	UINT nID;        // control ID (or 0 for windows messages)
	UINT nLastID;    // used for entries specifying a range of control id's
	UINT_PTR nSig;   // signature type (action) or pointer to message #
	AFX_PMSG pfn;    // routine to call (or special value)
};

struct AFX_MSGMAP
{
	const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
	const AFX_MSGMAP_ENTRY* lpEntries;
};

// 这里即息映射宏的主体
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
	PTM_WARNING_DISABLE \
	const AFX_MSGMAP* theClass::GetMessageMap() const \
		{ return GetThisMessageMap(); } \
	const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
	{ \
		typedef theClass ThisClass;						   \
		typedef baseClass TheBaseClass;					   \
		static const AFX_MSGMAP_ENTRY _messageEntries[] =  \
		{

#define END_MESSAGE_MAP() \
		{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
	}; \
		static const AFX_MSGMAP messageMap = \
		{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
		return &messageMap; \
	}								  \
	PTM_WARNING_RESTORE

#define ON_WM_SYSCOMMAND() \
	{ WM_SYSCOMMAND, 0, 0, 0, AfxSig_vwl, \
		(AFX_PMSG)(AFX_PMSGW) \
		(static_cast< void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM) > ( &ThisClass :: OnSysCommand)) },

// 根据上面的宏定义,可将下面的宏进行展开
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_BN_CLICKED(IDC_BUTTON_MESSAGE, &CTestDlg::OnBnClickedButtonMessage)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, &CTestDlg::OnLvnItemchangedList)
END_MESSAGE_MAP()
   
const AFX_MSGMAP* theClass::GetMessageMap() const 
{     
	  return GetThisMessageMap(); 
} 
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() 
{ 
	typedef theClass ThisClass;						   
	typedef baseClass TheBaseClass;		

	static const AFX_MSGMAP_ENTRY _messageEntries[] =  
	{
		{ WM_SYSCOMMAND, 0, 0, 0, AfxSig_vwl, (AFX_PMSG)(AFX_PMSGW)(static_cast<void (AFX_MSG_CALL CWnd::*)(UINT, LPARAM)>(&ThisClass::OnSysCommand)) },
		{ WM_PAINT, 0, 0, 0, AfxSig_vv, (AFX_PMSG)(AFX_PMSGW)(static_cast<void (AFX_MSG_CALL CWnd::*)(void)>(&ThisClass::OnPaint)) },
		{ WM_COMMAND, (WORD)wNotifyCode, (WORD)id, (WORD)id, AfxSigCmd_v, (static_cast<AFX_PMSG>(memberFxn)) },
		{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, (AFX_PMSG)(static_cast<void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*)>(memberFxn)) },
		{ 0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } 
	}; 

	static const AFX_MSGMAP messageMap = 
	{ 
		&TheBaseClass::GetThisMessageMap, 
		&_messageEntries[0] 
	}; 
	
	return &messageMap; 
}						
2、扩展(自定义)消息

// afxmsg_.h
// User extensions for message map entries

// for Windows messages
#define ON_MESSAGE(message, memberFxn) \
	{ message, 0, 0, 0, AfxSig_lwl, \
		(AFX_PMSG)(AFX_PMSGW) \
		(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
		(memberFxn)) },

// for Registered Windows messages
#define ON_REGISTERED_MESSAGE(nMessageVariable, memberFxn) \
	{ 0xC000, 0, 0, 0, (UINT_PTR)(UINT*)(&nMessageVariable), \
		/*implied 'AfxSig_lwl'*/ \
		(AFX_PMSG)(AFX_PMSGW) \
		(static_cast< LRESULT (AFX_MSG_CALL CWnd::*)(WPARAM, LPARAM) > \
		(memberFxn)) },

// for Thread messages
#define ON_THREAD_MESSAGE(message, memberFxn) \
	{ message, 0, 0, 0, AfxSig_vwl, \
		(AFX_PMSG)(AFX_PMSGT) \
		(static_cast< void (AFX_MSG_CALL CWinThread::*)(WPARAM, LPARAM) > \
		(memberFxn)) },

// for Registered Windows messages
#define ON_REGISTERED_THREAD_MESSAGE(nMessageVariable, memberFxn) \
	{ 0xC000, 0, 0, 0, (UINT_PTR)(UINT*)(&nMessageVariable), \
		/*implied 'AfxSig_vwl'*/ \
		(AFX_PMSG)(AFX_PMSGT) \
		(static_cast< void (AFX_MSG_CALL CWinThread::*)(WPARAM, LPARAM) > \
		(memberFxn)) },

3、消息调用的实现(参见wincore.cpp)

BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
	LRESULT lResult = 0;
	union MessageMapFunctions mmf;
	mmf.pfn = 0;
	CInternalGlobalLock winMsgLock;
	// special case for commands
	if (message == WM_COMMAND)
	{
		if (OnCommand(wParam, lParam))
		{
			lResult = 1;
			goto LReturnTrue;
		}
		return FALSE;
	}

	// special case for notifies
	if (message == WM_NOTIFY)
	{
		NMHDR* pNMHDR = (NMHDR*)lParam;
		if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
			goto LReturnTrue;
		return FALSE;
	}

	// special case for activation
	if (message == WM_ACTIVATE)
		_AfxHandleActivate(this, wParam, CWnd::FromHandle((HWND)lParam));

	// special case for set cursor HTERROR
	if (message == WM_SETCURSOR &&
		_AfxHandleSetCursor(this, (short)LOWORD(lParam), HIWORD(lParam)))
	{
		lResult = 1;
		goto LReturnTrue;
	}

   // special case for windows that contain windowless ActiveX controls
   BOOL bHandled;

   bHandled = FALSE;
   if ((m_pCtrlCont != NULL) && (m_pCtrlCont->m_nWindowlessControls > 0))
   {
	  if (((message >= WM_MOUSEFIRST) && (message <= AFX_WM_MOUSELAST)) ||
		 ((message >= WM_KEYFIRST) && (message <= WM_IME_KEYLAST)) ||
		 ((message >= WM_IME_SETCONTEXT) && (message <= WM_IME_KEYUP)))
	  {
		 bHandled = m_pCtrlCont->HandleWindowlessMessage(message, wParam, lParam, &lResult);
	  }
   }
   if (bHandled)
   {
	  goto LReturnTrue;
   }

	const AFX_MSGMAP* pMessageMap; pMessageMap = GetMessageMap();
	UINT iHash; iHash = (LOWORD((DWORD_PTR)pMessageMap) ^ message) & (iHashMax-1);
	winMsgLock.Lock(CRIT_WINMSGCACHE);
	AFX_MSG_CACHE* pMsgCache; pMsgCache = &_afxMsgCache[iHash];
	const AFX_MSGMAP_ENTRY* lpEntry;
	if (message == pMsgCache->nMsg && pMessageMap == pMsgCache->pMessageMap)
	{
		// cache hit
		lpEntry = pMsgCache->lpEntry;
		winMsgLock.Unlock();
		if (lpEntry == NULL)
			return FALSE;

		// cache hit, and it needs to be handled
		if (message < 0xC000)
			goto LDispatch;
		else
			goto LDispatchRegistered;
	}
	else
	{
		// not in cache, look for it
		pMsgCache->nMsg = message;
		pMsgCache->pMessageMap = pMessageMap;

		for (/* pMessageMap already init'ed */; pMessageMap->pfnGetBaseMap != NULL;
			pMessageMap = (*pMessageMap->pfnGetBaseMap)())
		{
			// Note: catch not so common but fatal mistake!!
			//      BEGIN_MESSAGE_MAP(CMyWnd, CMyWnd)
			ASSERT(pMessageMap != (*pMessageMap->pfnGetBaseMap)());
			if (message < 0xC000)
			{
				// constant window message
				if ((lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,
					message, 0, 0)) != NULL)
				{
					pMsgCache->lpEntry = lpEntry;
					winMsgLock.Unlock();
					goto LDispatch;
				}
			}
			else
			{
				// registered windows message
				lpEntry = pMessageMap->lpEntries;
				while ((lpEntry = AfxFindMessageEntry(lpEntry, 0xC000, 0, 0)) != NULL)
				{
					UINT* pnID = (UINT*)(lpEntry->nSig);
					ASSERT(*pnID >= 0xC000 || *pnID == 0);
						// must be successfully registered
					if (*pnID == message)
					{
						pMsgCache->lpEntry = lpEntry;
						winMsgLock.Unlock();
						goto LDispatchRegistered;
					}
					lpEntry++;      // keep looking past this one
				}
			}
		}

		pMsgCache->lpEntry = NULL;
		winMsgLock.Unlock();
		return FALSE;
	}

LDispatch:
	ASSERT(message < 0xC000);

	mmf.pfn = lpEntry->pfn;

	switch (lpEntry->nSig)
	{
	default:
		ASSERT(FALSE);
		break;
	case AfxSig_l_p:
		{
			CPoint point(lParam);		
			lResult = (this->*mmf.pfn_l_p)(point);
			break;
		}		
	case AfxSig_b_D_v:
		lResult = (this->*mmf.pfn_b_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
		break;

	case AfxSig_b_b_v:
		lResult = (this->*mmf.pfn_b_b)(static_cast<BOOL>(wParam));
		break;

	case AfxSig_b_u_v:
		lResult = (this->*mmf.pfn_b_u)(static_cast<UINT>(wParam));
		break;

	case AfxSig_b_h_v:
		lResult = (this->*mmf.pfn_b_h)(reinterpret_cast<HANDLE>(wParam));
		break;

	case AfxSig_i_u_v:
		lResult = (this->*mmf.pfn_i_u)(static_cast<UINT>(wParam));
		break;

	case AfxSig_C_v_v:
		lResult = reinterpret_cast<LRESULT>((this->*mmf.pfn_C_v)());
		break;

	case AfxSig_v_u_W:
		(this->*mmf.pfn_v_u_W)(static_cast<UINT>(wParam), 
			CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
		break;

	case AfxSig_u_u_v:
		lResult = (this->*mmf.pfn_u_u)(static_cast<UINT>(wParam));
		break;

	case AfxSig_b_v_v:
		lResult = (this->*mmf.pfn_b_v)();
		break;

	case AfxSig_b_W_uu:
		lResult = (this->*mmf.pfn_b_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
			LOWORD(lParam), HIWORD(lParam));
		break;

	case AfxSig_b_W_COPYDATASTRUCT:
		lResult = (this->*mmf.pfn_b_W_COPYDATASTRUCT)(
			CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
			reinterpret_cast<COPYDATASTRUCT*>(lParam));
		break;

	case AfxSig_b_v_HELPINFO:
		lResult = (this->*mmf.pfn_b_HELPINFO)(reinterpret_cast<LPHELPINFO>(lParam));
		break;

	case AfxSig_CTLCOLOR:
		{
			// special case for OnCtlColor to avoid too many temporary objects
			ASSERT(message == WM_CTLCOLOR);
			AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
			CDC dcTemp; 
			dcTemp.m_hDC = pCtl->hDC;
			CWnd wndTemp; 
			wndTemp.m_hWnd = pCtl->hWnd;
			UINT nCtlType = pCtl->nCtlType;
			// if not coming from a permanent window, use stack temporary
			CWnd* pWnd = CWnd::FromHandlePermanent(wndTemp.m_hWnd);
			if (pWnd == NULL)
			{
#ifndef _AFX_NO_OCC_SUPPORT
				// determine the site of the OLE control if it is one
				COleControlSite* pSite;
				if (m_pCtrlCont != NULL && (pSite = (COleControlSite*)
					m_pCtrlCont->m_siteMap.GetValueAt(wndTemp.m_hWnd)) != NULL)
				{
					wndTemp.m_pCtrlSite = pSite;
				}
#endif
				pWnd = &wndTemp;
			}
			HBRUSH hbr = (this->*mmf.pfn_B_D_W_u)(&dcTemp, pWnd, nCtlType);
			// fast detach of temporary objects
			dcTemp.m_hDC = NULL;
			wndTemp.m_hWnd = NULL;
			lResult = reinterpret_cast<LRESULT>(hbr);
		}
		break;

	case AfxSig_CTLCOLOR_REFLECT:
		{
			// special case for CtlColor to avoid too many temporary objects
			ASSERT(message == WM_REFLECT_BASE+WM_CTLCOLOR);
			AFX_CTLCOLOR* pCtl = reinterpret_cast<AFX_CTLCOLOR*>(lParam);
			CDC dcTemp; 
			dcTemp.m_hDC = pCtl->hDC;
			UINT nCtlType = pCtl->nCtlType;
			HBRUSH hbr = (this->*mmf.pfn_B_D_u)(&dcTemp, nCtlType);
			// fast detach of temporary objects
			dcTemp.m_hDC = NULL;
			lResult = reinterpret_cast<LRESULT>(hbr);
		}
		break;

	case AfxSig_i_u_W_u:
		lResult = (this->*mmf.pfn_i_u_W_u)(LOWORD(wParam),
			CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
		break;

	case AfxSig_i_uu_v:
		lResult = (this->*mmf.pfn_i_u_u)(LOWORD(wParam), HIWORD(wParam));
		break;

	case AfxSig_i_W_uu:
		lResult = (this->*mmf.pfn_i_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
			LOWORD(lParam), HIWORD(lParam));
		break;

	case AfxSig_i_v_s:
		lResult = (this->*mmf.pfn_i_s)(reinterpret_cast<LPTSTR>(lParam));
		break;

	case AfxSig_l_w_l:
		lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
		break;

	case AfxSig_l_uu_M:
		lResult = (this->*mmf.pfn_l_u_u_M)(LOWORD(wParam), HIWORD(wParam), 
			CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
		break;
		
	case AfxSig_v_b_h:
	    (this->*mmf.pfn_v_b_h)(static_cast<BOOL>(wParam), 
			reinterpret_cast<HANDLE>(lParam));
		break;

	case AfxSig_v_h_v:
	    (this->*mmf.pfn_v_h)(reinterpret_cast<HANDLE>(wParam));
		break;

	case AfxSig_v_h_h:
	    (this->*mmf.pfn_v_h_h)(reinterpret_cast<HANDLE>(wParam), 
			reinterpret_cast<HANDLE>(lParam));
		break;

	case AfxSig_v_v_v:
		(this->*mmf.pfn_v_v)();
		break;

	case AfxSig_v_u_v:
		(this->*mmf.pfn_v_u)(static_cast<UINT>(wParam));
		break;

	case AfxSig_v_u_u:
		(this->*mmf.pfn_v_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
		break;

	case AfxSig_v_uu_v:
		(this->*mmf.pfn_v_u_u)(LOWORD(wParam), HIWORD(wParam));
		break;

	case AfxSig_v_v_ii:
		(this->*mmf.pfn_v_i_i)(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
		break;

	case AfxSig_v_u_uu:
		(this->*mmf.pfn_v_u_u_u)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
		break;

	case AfxSig_v_u_ii:
		(this->*mmf.pfn_v_u_i_i)(static_cast<UINT>(wParam), LOWORD(lParam), HIWORD(lParam));
		break;

	case AfxSig_v_w_l:
		(this->*mmf.pfn_v_w_l)(wParam, lParam);
		break;

	case AfxSig_MDIACTIVATE:
		(this->*mmf.pfn_v_b_W_W)(m_hWnd == reinterpret_cast<HWND>(lParam),
			CWnd::FromHandle(reinterpret_cast<HWND>(lParam)),
			CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
		break;

	case AfxSig_v_D_v:
		(this->*mmf.pfn_v_D)(CDC::FromHandle(reinterpret_cast<HDC>(wParam)));
		break;

	case AfxSig_v_M_v:
		(this->*mmf.pfn_v_M)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)));
		break;

	case AfxSig_v_M_ub:
		(this->*mmf.pfn_v_M_u_b)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)),
			GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
		break;

	case AfxSig_v_W_v:
		(this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)));
		break;

	case AfxSig_v_v_W:
		(this->*mmf.pfn_v_W)(CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
		break;

	case AfxSig_v_W_uu:
		(this->*mmf.pfn_v_W_u_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), LOWORD(lParam),
			HIWORD(lParam));
		break;

	case AfxSig_v_W_p:
		{
			CPoint point(lParam);
			(this->*mmf.pfn_v_W_p)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), point);
		}
		break;

	case AfxSig_v_W_h:
		(this->*mmf.pfn_v_W_h)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)),
				reinterpret_cast<HANDLE>(lParam));
		break;

	case AfxSig_ACTIVATE:
		(this->*mmf.pfn_v_u_W_b)(LOWORD(wParam),
			CWnd::FromHandle(reinterpret_cast<HWND>(lParam)), HIWORD(wParam));
		break;

	case AfxSig_SCROLL:
	case AfxSig_SCROLL_REFLECT:
		{
			// special case for WM_VSCROLL and WM_HSCROLL
			ASSERT(message == WM_VSCROLL || message == WM_HSCROLL ||
				message == WM_VSCROLL+WM_REFLECT_BASE || message == WM_HSCROLL+WM_REFLECT_BASE);
			int nScrollCode = (short)LOWORD(wParam);
			int nPos = (short)HIWORD(wParam);
			if (lpEntry->nSig == AfxSig_SCROLL)
				(this->*mmf.pfn_v_u_u_W)(nScrollCode, nPos,
					CWnd::FromHandle(reinterpret_cast<HWND>(lParam)));
			else
				(this->*mmf.pfn_v_u_u)(nScrollCode, nPos);
		}
		break;

	case AfxSig_v_v_s:
		(this->*mmf.pfn_v_s)(reinterpret_cast<LPTSTR>(lParam));
		break;

	case AfxSig_v_u_cs:
		(this->*mmf.pfn_v_u_cs)(static_cast<UINT>(wParam), reinterpret_cast<LPCTSTR>(lParam));
		break;

	case AfxSig_OWNERDRAW:
		(this->*mmf.pfn_v_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
		lResult = TRUE;
		break;

	case AfxSig_i_i_s:
		lResult = (this->*mmf.pfn_i_i_s)(static_cast<int>(wParam), reinterpret_cast<LPTSTR>(lParam));
		break;

	case AfxSig_u_v_p:
		{
			CPoint point(lParam);
			lResult = (this->*mmf.pfn_u_p)(point);
		}
		break;

	case AfxSig_u_v_v:
		lResult = (this->*mmf.pfn_u_v)();
		break;

	case AfxSig_v_b_NCCALCSIZEPARAMS:
		(this->*mmf.pfn_v_b_NCCALCSIZEPARAMS)(static_cast<BOOL>(wParam), 
			reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam));
		break;

	case AfxSig_v_v_WINDOWPOS:
		(this->*mmf.pfn_v_v_WINDOWPOS)(reinterpret_cast<WINDOWPOS*>(lParam));
		break;

	case AfxSig_v_uu_M:
		(this->*mmf.pfn_v_u_u_M)(LOWORD(wParam), HIWORD(wParam), reinterpret_cast<HMENU>(lParam));
		break;

	case AfxSig_v_u_p:
		{
			CPoint point(lParam);
			(this->*mmf.pfn_v_u_p)(static_cast<UINT>(wParam), point);
		}
		break;

	case AfxSig_SIZING:
		(this->*mmf.pfn_v_u_pr)(static_cast<UINT>(wParam), reinterpret_cast<LPRECT>(lParam));
		lResult = TRUE;
		break;

	case AfxSig_MOUSEWHEEL:
		lResult = (this->*mmf.pfn_b_u_s_p)(LOWORD(wParam), (short)HIWORD(wParam),
			CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
		if (!lResult)
			return FALSE;
		break;
	case AfxSig_MOUSEHWHEEL:
		(this->*mmf.pfn_MOUSEHWHEEL)(LOWORD(wParam), (short)HIWORD(wParam),
			CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
		break;
	case AfxSig_l:
		lResult = (this->*mmf.pfn_l_v)();
		if (lResult != 0)
			return FALSE;
		break;
	case AfxSig_u_W_u:
		lResult = (this->*mmf.pfn_u_W_u)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(lParam));
		break;
	case AfxSig_v_u_M:
		(this->*mmf.pfn_v_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
		break;
	case AfxSig_u_u_M:
		lResult = (this->*mmf.pfn_u_u_M)(static_cast<UINT>(wParam), CMenu::FromHandle(reinterpret_cast<HMENU>(lParam)));
		break;
	case AfxSig_u_v_MENUGETOBJECTINFO:
		lResult = (this->*mmf.pfn_u_v_MENUGETOBJECTINFO)(reinterpret_cast<MENUGETOBJECTINFO*>(lParam));
		break;
	case AfxSig_v_M_u:
		(this->*mmf.pfn_v_M_u)(CMenu::FromHandle(reinterpret_cast<HMENU>(wParam)), static_cast<UINT>(lParam));
		break;
	case AfxSig_v_u_LPMDINEXTMENU:
		(this->*mmf.pfn_v_u_LPMDINEXTMENU)(static_cast<UINT>(wParam), reinterpret_cast<LPMDINEXTMENU>(lParam));
		break;
	case AfxSig_APPCOMMAND:
		(this->*mmf.pfn_APPCOMMAND)(CWnd::FromHandle(reinterpret_cast<HWND>(wParam)), static_cast<UINT>(GET_APPCOMMAND_LPARAM(lParam)), static_cast<UINT>(GET_DEVICE_LPARAM(lParam)), static_cast<UINT>(GET_KEYSTATE_LPARAM(lParam)));
		lResult = TRUE;
		break;
	case AfxSig_RAWINPUT:
		(this->*mmf.pfn_RAWINPUT)(static_cast<UINT>(GET_RAWINPUT_CODE_WPARAM(wParam)), reinterpret_cast<HRAWINPUT>(lParam));
		break;
	case AfxSig_u_u_u:
		lResult = (this->*mmf.pfn_u_u_u)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
		break;
	case AfxSig_MOUSE_XBUTTON:
		(this->*mmf.pfn_MOUSE_XBUTTON)(static_cast<UINT>(GET_KEYSTATE_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
		lResult = TRUE;
		break;
	case AfxSig_MOUSE_NCXBUTTON:
		(this->*mmf.pfn_MOUSE_NCXBUTTON)(static_cast<short>(GET_NCHITTEST_WPARAM(wParam)), static_cast<UINT>(GET_XBUTTON_WPARAM(wParam)), CPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
		lResult = TRUE;
		break;
	case AfxSig_INPUTLANGCHANGE:
		(this->*mmf.pfn_INPUTLANGCHANGE)(static_cast<UINT>(wParam), static_cast<UINT>(lParam));
		lResult = TRUE;
		break;
	case AfxSig_INPUTDEVICECHANGE:
		(this->*mmf.pfn_INPUTDEVICECHANGE)(GET_DEVICE_CHANGE_LPARAM(wParam), reinterpret_cast<HANDLE>(lParam));
		break;
	case AfxSig_v_u_hkl:
		(this->*mmf.pfn_v_u_h)(static_cast<UINT>(wParam), reinterpret_cast<HKL>(lParam));
		break;
	}
	goto LReturnTrue;

LDispatchRegistered:    // for registered windows messages
	ASSERT(message >= 0xC000);
	ASSERT(sizeof(mmf) == sizeof(mmf.pfn));
	mmf.pfn = lpEntry->pfn;
	lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);

LReturnTrue:
	if (pResult != NULL)
		*pResult = lResult;
	return TRUE;
}



总结

1、MFC的消息映射即关于消息与消息处理函数之间的一张静态表。

总结二、MFC消息映射_第1张图片

2、自定义消息
(1)定义消息
#define WM_MYMSG_TEST  WM_USER + 1000
(2)添加消息映射
BEGIN_MESSAGE_MAP(CTestDlg, CDialog)
ON_MESSAGE(WM_MYMSG_TEST, OnMyMsgTest)
END_MESSAGE_MAP()
(3)声明消息处理函数
afx_msg LRESULT OnMyMsgTest(WPARAM wParam, LPARAM lParam);
(4)实现消息处理函数
LRESULT OnMyMsgTest(WPARAM wParam, LPARAM lParam)
{
MessageBox("Hello, world!");

return 0;
}

微笑奋斗

你可能感兴趣的:(总结二、MFC消息映射)