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的消息映射即关于消息与消息处理函数之间的一张静态表。
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;
}