MFC 消息机制
MFC消息映射
首先产生钩子,截取所有的消息 包括NCcreate
AfxHookWindowCreate(this); void AFXAPI AfxHookWindowCreate(CWnd* pWnd) { //获取线程状态开是否设置钩子,没设置设置一下。 _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); if (pThreadState->m_pWndInit == pWnd) return; if (pThreadState->m_hHookOldCbtFilter == NULL) { 设置钩子截取所有函数 pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT, _AfxCbtFilterHook, NULL, ::GetCurrentThreadId()); if (pThreadState->m_hHookOldCbtFilter == NULL) AfxThrowMemoryException(); } pThreadState->m_pWndInit = pWnd; } 钩子的线程函数 LRESULT CALLBACK _AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam) { _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); CWnd* pWndInit = pThreadState->m_pWndInit; HWND hWnd = (HWND)wParam; WNDPROC oldWndProc; if (pWndInit != NULL) { AFX_MANAGE_STATE(pWndInit->m_pModuleState); // 将消息和句柄对应起来 pWndInit->Attach(hWnd); //允许先进行其他子类化 pWndInit->PreSubclassWindow(); // 用标准子类化窗口 AfxWndProc WNDPROC afxWndProc = AfxGetAfxWndProc(); 设置窗口过程函数 oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc); if (oldWndProc != afxWndProc) *pOldWndProc = oldWndProc; pThreadState->m_pWndInit = NULL; } return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code, } BOOL CWnd::Attach(HWND hWndNew) { if (hWndNew == NULL) return FALSE; 、、如果不存在,创建映射 CHandleMap* pMap = afxMapHWND(TRUE); 添加映射 pMap->SetPermanent(m_hWnd = hWndNew, this); AttachControlSite(pMap); return TRUE; } CHandleMap* PASCAL afxMapHWND(BOOL bCreate) { AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState(); return pState->m_pmapHWND; } LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { 、、所有其他消息都通过消息映射路由 CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam); } CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd) { 查表,获得对应的CWND* CHandleMap* pMap = afxMapHWND(); pWnd = (CWnd*)pMap->LookupPermanent(hWnd); return pWnd; } void AFXAPI _AfxTraceMsg(LPCTSTR lpszPrefix, const MSG* pMsg) { 消息查表 const AFX_MAP_MESSAGE* pMapMsg = allMessages; for (/*null*/; pMapMsg->lpszMsg != NULL; pMapMsg++) { if (pMapMsg->nMsg == pMsg->message) { lpszMsgName = pMapMsg->lpszMsg; break; } } LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0) { 获取线程状态 _AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData(); 保存消息 嵌套 MSG oldState = pThreadState->m_lastSentMsg; pThreadState->m_lastSentMsg.hwnd = hWnd; pThreadState->m_lastSentMsg.message = nMsg; pThreadState->m_lastSentMsg.wParam = wParam; pThreadState->m_lastSentMsg.lParam = lParam; // Catch exceptions thrown outside the scope of a callback // in debug builds and warn the user. LRESULT lResult; 调用WindowProc回调函数 lResult = pWnd->WindowProc(nMsg, wParam, lParam); pThreadState->m_lastSentMsg = oldState; return lResult; } LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // 这里面调用查找进入对应的消息入口 LRESULT lResult = 0; if (!OnWndMsg(message, wParam, lParam, &lResult)) lResult = DefWindowProc(message, wParam, lParam); return lResult; } BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) 这个函数中判定了消息的种类和调用不同的对应函数 查对应函数入口
太多了做个标号在 wincore.cpp 中的第2279行
然后在调对应的函数
struct AFX_MAP_MESSAGE { UINT nMsg; LPCSTR lpszMsg; }; 消息定义 static const AFX_MAP_MESSAGE allMessages[] = { DEFINE_MESSAGE(WM_CREATE), DEFINE_MESSAGE(WM_DESTROY), ············· DEFINE_MESSAGE(WM_DEVICECHANGE), { 0, NULL, } // end of message list }; #define DECLARE_MESSAGE_MAP() \ protected: \ static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \ virtual const AFX_MSGMAP* GetMessageMap() const; \ struct AFX_MSGMAP { 基类指针 const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)(); 自己的消息信息 const AFX_MSGMAP_ENTRY* lpEntries; }; struct AFX_MSGMAP_ENTRY { UINT nMessage; UINT nCode; windows消息 UINT nID; 控件ID(或0用于windows消息) UINT nLastID; 用于指定控件id范围的条目 UINT_PTR nSig; 指向消息的指针类型标志 AFX_PMSG pfn; 函数指针 }; 消息一般重新cWnd的虚函数
实现宏中的开始消息 #define BEGIN_TEMPLATE_MESSAGE_MAP(theClass, type_name, baseClass) \ PTM_WARNING_DISABLE \ template < typename type_name > \ const AFX_MSGMAP* theClass< type_name >::GetMessageMap() const \ { return GetThisMessageMap(); } \ template < typename type_name > \ const AFX_MSGMAP* PASCAL theClass< type_name >::GetThisMessageMap() \ { \ typedef theClass< type_name > ThisClass; \ typedef baseClass TheBaseClass; \ __pragma(warning(push)) \ __pragma(warning(disable: 4640)) /* message maps can only be called by single threaded message pump */ \ static const AFX_MSGMAP_ENTRY _messageEntries[] = \ { 实现宏中的结束消息 #define END_MESSAGE_MAP() \ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ }; \ __pragma(warning(pop)) \ static const AFX_MSGMAP messageMap = \ { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \ return &messageMap; \ } \ PTM_WARNING_RESTORE 函数指针公用体 union MessageMapFunctions { AFX_PMSG pfn; // generic member function pointer BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_D)(CDC*); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_b)(BOOL); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_u)(UINT); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_h)(HANDLE); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_u_u)(CWnd*, UINT, UINT); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_COPYDATASTRUCT)(CWnd*, COPYDATASTRUCT*); BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_HELPINFO)(LPHELPINFO); HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_W_u)(CDC*, CWnd*, UINT); HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_u)(CDC*, UINT); int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_W_u)(UINT, CWnd*, UINT); int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_u)(UINT, UINT); int (AFX_MSG_CALL CCmdTarget::*pfn_i_W_u_u)(CWnd*, UINT, UINT); int (AFX_MSG_CALL CWnd::*pfn_i_s)(LPTSTR); int (AFX_MSG_CALL CWnd::*pfn_i_S)(LPCTSTR); LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM); LRESULT (AFX_MSG_CALL CWnd::*pfn_l_u_u_M)(UINT, UINT, CMenu*); void (AFX_MSG_CALL CWnd::*pfn_v_b_h)(BOOL, HANDLE); void (AFX_MSG_CALL CWnd::*pfn_v_h)(HANDLE); void (AFX_MSG_CALL CWnd::*pfn_v_h_h)(HANDLE,HANDLE); void (AFX_MSG_CALL CWnd::*pfn_v_v)(); int (AFX_MSG_CALL CWnd::*pfn_i_u)(UINT); HCURSOR (AFX_MSG_CALL CWnd::*pfn_C_v)(); UINT (AFX_MSG_CALL CWnd::*pfn_u_u)(UINT); BOOL (AFX_MSG_CALL CWnd::*pfn_b_v)(); void (AFX_MSG_CALL CWnd::*pfn_v_u)(UINT); void (AFX_MSG_CALL CWnd::*pfn_v_up)(UINT_PTR); void (AFX_MSG_CALL CWnd::*pfn_v_u_u)(UINT, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_i_i)(int, int); void (AFX_MSG_CALL CWnd::*pfn_v_u_u_u)(UINT, UINT, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_u_i_i)(UINT, int, int); void (AFX_MSG_CALL CWnd::*pfn_v_w_l)(WPARAM, LPARAM); void (AFX_MSG_CALL CWnd::*pfn_v_b_W_W)(BOOL, CWnd*, CWnd*); void (AFX_MSG_CALL CWnd::*pfn_v_D)(CDC*); void (AFX_MSG_CALL CWnd::*pfn_v_M)(CMenu*); void (AFX_MSG_CALL CWnd::*pfn_v_M_u_b)(CMenu*, UINT, BOOL); void (AFX_MSG_CALL CWnd::*pfn_v_W)(CWnd*); void (AFX_MSG_CALL CWnd::*pfn_v_W_u_u)(CWnd*, UINT, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_W_p)(CWnd*, CPoint); void (AFX_MSG_CALL CWnd::*pfn_v_W_h)(CWnd*, HANDLE); void (AFX_MSG_CALL CWnd::*pfn_v_u_W)(UINT, CWnd*); void (AFX_MSG_CALL CWnd::*pfn_v_u_W_b)(UINT, CWnd*, BOOL); void (AFX_MSG_CALL CWnd::*pfn_v_u_u_W)(UINT, UINT, CWnd*); void (AFX_MSG_CALL CWnd::*pfn_v_s)(LPTSTR); void (AFX_MSG_CALL CWnd::*pfn_v_u_cs)(UINT, LPCTSTR); void (AFX_MSG_CALL CWnd::*pfn_v_i_s)(int, LPTSTR); int (AFX_MSG_CALL CWnd::*pfn_i_i_s)(int, LPTSTR); UINT (AFX_MSG_CALL CWnd::*pfn_u_p)(CPoint); LRESULT (AFX_MSG_CALL CWnd::*pfn_l_p)(CPoint); UINT (AFX_MSG_CALL CWnd::*pfn_u_v)(); void (AFX_MSG_CALL CWnd::*pfn_v_b_NCCALCSIZEPARAMS)(BOOL, NCCALCSIZE_PARAMS*); void (AFX_MSG_CALL CWnd::*pfn_v_v_WINDOWPOS)(WINDOWPOS*); void (AFX_MSG_CALL CWnd::*pfn_v_u_u_M)(UINT, UINT, HMENU); void (AFX_MSG_CALL CWnd::*pfn_v_u_p)(UINT, CPoint); void (AFX_MSG_CALL CWnd::*pfn_v_u_pr)(UINT, LPRECT); BOOL (AFX_MSG_CALL CWnd::*pfn_b_u_s_p)(UINT, short, CPoint); void (AFX_MSG_CALL CWnd::*pfn_MOUSEHWHEEL)(UINT, short, CPoint); LRESULT (AFX_MSG_CALL CWnd::*pfn_l_v)(); UINT (AFX_MSG_CALL CWnd::*pfn_u_W_u)(CWnd*, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_u_M)(UINT, CMenu*); UINT (AFX_MSG_CALL CWnd::*pfn_u_u_M)(UINT, CMenu*); UINT (AFX_MSG_CALL CWnd::*pfn_u_v_MENUGETOBJECTINFO)(MENUGETOBJECTINFO*); void (AFX_MSG_CALL CWnd::*pfn_v_M_u)(CMenu*, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_u_LPMDINEXTMENU)(UINT, LPMDINEXTMENU); void (AFX_MSG_CALL CWnd::*pfn_APPCOMMAND)(CWnd*, UINT, UINT, UINT); BOOL (AFX_MSG_CALL CWnd::*pfn_RAWINPUT)(UINT, HRAWINPUT); UINT (AFX_MSG_CALL CWnd::*pfn_u_u_u)(UINT, UINT); UINT (AFX_MSG_CALL CWnd::*pfn_u_u_l)(UINT, LPARAM); void (AFX_MSG_CALL CWnd::*pfn_MOUSE_XBUTTON)(UINT, UINT, CPoint); void (AFX_MSG_CALL CWnd::*pfn_MOUSE_NCXBUTTON)(short, UINT, CPoint); void (AFX_MSG_CALL CWnd::*pfn_INPUTLANGCHANGE)(UINT, UINT); BOOL (AFX_MSG_CALL CWnd::*pfn_v_u_h)(UINT, HANDLE); void (AFX_MSG_CALL CWnd::*pfn_INPUTDEVICECHANGE)(unsigned short, HANDLE); LRESULT (AFX_MSG_CALL CWnd::*pfn_l_D_u)(CDC*, UINT); void (AFX_MSG_CALL CWnd::*pfn_v_F_b)(CFont*, BOOL); HANDLE (AFX_MSG_CALL CWnd::*pfn_h_v)(); HANDLE (AFX_MSG_CALL CWnd::*pfn_h_b_h)(BOOL, HANDLE); BOOL (AFX_MSG_CALL CWnd::*pfn_b_v_ii)(int, int); HANDLE (AFX_MSG_CALL CWnd::*pfn_h_h_h)(HANDLE, HANDLE); void (AFX_MSG_CALL CWnd::*pfn_v_W_b)(CWnd*, BOOL); // type safe variant for thread messages void (AFX_MSG_CALL CWinThread::*pfn_THREAD)(WPARAM, LPARAM); // specific type safe variants for WM_COMMAND and WM_NOTIFY messages void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_v)(); BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_v)(); void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_u)(UINT); BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_u)(UINT); void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_NMHDR_pl)(NMHDR*, LRESULT*); BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_NMHDR_pl)(NMHDR*, LRESULT*); void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*); BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*); void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C)(CCmdUI*); void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C_u)(CCmdUI*, UINT); void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_pv)(void*); BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_pv)(void*); }; 下面是部分的消息 在afxmsg.cpp中的267行 太多了 截取一点做列子 #define ON_COMMAND(id, memberFxn) \ { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \ static_cast<AFX_PMSG> (memberFxn) }, // ON_COMMAND(id, OnBar) is the same as // ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar) #define ON_COMMAND_RANGE(id, idLast, memberFxn) \ { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_RANGE, \ (AFX_PMSG) \ (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT) > \ (memberFxn)) }, // ON_COMMAND_RANGE(id, idLast, OnBar) is the same as // ON_CONTROL_RANGE(0, id, idLast, OnBar) #define ON_COMMAND_EX(id, memberFxn) \ { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_EX, \ (AFX_PMSG) \ (static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT) > \ (memberFxn)) }, #define ON_COMMAND_EX_RANGE(id, idLast, memberFxn) \ { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_EX, \ (AFX_PMSG) \ (static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT) > \ (memberFxn)) }, // update ui's are listed as WM_COMMAND's so they get routed like commands #define ON_UPDATE_COMMAND_UI(id, memberFxn) \ { WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)id, AfxSigCmdUI, \ (AFX_PMSG) \ (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \ (memberFxn)) }, #define ON_UPDATE_COMMAND_UI_RANGE(id, idLast, memberFxn) \ { WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)idLast, AfxSigCmdUI, \ (AFX_PMSG) \ (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \ (memberFxn)) }, #define ON_NOTIFY(wNotifyCode, id, memberFxn) \ { WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \ (AFX_PMSG) \ (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \ (memberFxn)) }, #define ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn) \ { WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)idLast, AfxSigNotify_RANGE, \ (AFX_PMSG) \ (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \ (memberFxn)) }, #define ON_NOTIFY_EX(wNotifyCode, id, memberFxn) \ { WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_EX, \ (AFX_PMSG) \ (static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \ (memberFxn)) }, #define ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn) \ { WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)idLast, AfxSigNotify_EX, \ (AFX_PMSG) \ (static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \ (memberFxn)) },
MFC消息映射
首先产生钩子,截取所有的消息 包括NCcreate
AfxHookWindowCreate(this);
void AFXAPI AfxHookWindowCreate(CWnd* pWnd)
{
//获取线程状态开是否设置钩子,没设置设置一下。
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
if (pThreadState->m_pWndInit == pWnd)
return;
if (pThreadState->m_hHookOldCbtFilter == NULL)
{
设置钩子截取所有函数
pThreadState->m_hHookOldCbtFilter = ::SetWindowsHookEx(WH_CBT,
_AfxCbtFilterHook, NULL, ::GetCurrentThreadId());
if (pThreadState->m_hHookOldCbtFilter == NULL)
AfxThrowMemoryException();
}
pThreadState->m_pWndInit = pWnd;
}
钩子的线程函数
LRESULT CALLBACK
_AfxCbtFilterHook(int code, WPARAM wParam, LPARAM lParam)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
CWnd* pWndInit = pThreadState->m_pWndInit;
HWND hWnd = (HWND)wParam;
WNDPROC oldWndProc;
if (pWndInit != NULL)
{
AFX_MANAGE_STATE(pWndInit->m_pModuleState);
// 将消息和句柄对应起来
pWndInit->Attach(hWnd);
//允许先进行其他子类化
pWndInit->PreSubclassWindow();
// 用标准子类化窗口 AfxWndProc
WNDPROC afxWndProc = AfxGetAfxWndProc();
设置窗口过程函数
oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc);
if (oldWndProc != afxWndProc)
*pOldWndProc = oldWndProc;
pThreadState->m_pWndInit = NULL;
}
return CallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
}
BOOL CWnd::Attach(HWND hWndNew)
{
if (hWndNew == NULL)
return FALSE;
、、如果不存在,创建映射
CHandleMap* pMap = afxMapHWND(TRUE);
添加映射
pMap->SetPermanent(m_hWnd = hWndNew, this);
AttachControlSite(pMap);
return TRUE;
}
CHandleMap* PASCAL afxMapHWND(BOOL bCreate)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
return pState->m_pmapHWND;
}
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
、、所有其他消息都通过消息映射路由
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
return AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}
CWnd* PASCAL CWnd::FromHandlePermanent(HWND hWnd)
{
查表,获得对应的CWND*
CHandleMap* pMap = afxMapHWND();
pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
return pWnd;
}
void AFXAPI _AfxTraceMsg(LPCTSTR lpszPrefix, const MSG* pMsg)
{
消息查表
const AFX_MAP_MESSAGE* pMapMsg = allMessages;
for (/*null*/; pMapMsg->lpszMsg != NULL; pMapMsg++)
{
if (pMapMsg->nMsg == pMsg->message)
{
lpszMsgName = pMapMsg->lpszMsg;
break;
}
}
LRESULT AFXAPI AfxCallWndProc(CWnd* pWnd, HWND hWnd, UINT nMsg,
WPARAM wParam = 0, LPARAM lParam = 0)
{
获取线程状态
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
保存消息 嵌套
MSG oldState = pThreadState->m_lastSentMsg;
pThreadState->m_lastSentMsg.hwnd = hWnd;
pThreadState->m_lastSentMsg.message = nMsg;
pThreadState->m_lastSentMsg.wParam = wParam;
pThreadState->m_lastSentMsg.lParam = lParam;
// Catch exceptions thrown outside the scope of a callback
// in debug builds and warn the user.
LRESULT lResult;
调用WindowProc回调函数
lResult = pWnd->WindowProc(nMsg, wParam, lParam);
pThreadState->m_lastSentMsg = oldState;
return lResult;
}
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// 这里面调用查找进入对应的消息入口
LRESULT lResult = 0;
if (!OnWndMsg(message, wParam, lParam, &lResult))
lResult = DefWindowProc(message, wParam, lParam);
return lResult;
}
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
这个函数中判定了消息的种类和调用不同的对应函数
查对应函数入口
太多了做个标号在 wincore.cpp 中的第2279行
然后在调对应的函数
struct AFX_MAP_MESSAGE
{
UINT nMsg;
LPCSTR lpszMsg;
};
消息定义
static const AFX_MAP_MESSAGE allMessages[] =
{
DEFINE_MESSAGE(WM_CREATE),
DEFINE_MESSAGE(WM_DESTROY),
·············
DEFINE_MESSAGE(WM_DEVICECHANGE),
{ 0, NULL, } // end of message list
};
#define DECLARE_MESSAGE_MAP() \
protected: \
static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
virtual const AFX_MSGMAP* GetMessageMap() const; \
struct AFX_MSGMAP
{
基类指针
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
自己的消息信息
const AFX_MSGMAP_ENTRY* lpEntries;
};
struct AFX_MSGMAP_ENTRY
{
UINT nMessage;
UINT nCode; windows消息
UINT nID; 控件ID(或0用于windows消息)
UINT nLastID; 用于指定控件id范围的条目
UINT_PTR nSig; 指向消息的指针类型标志
AFX_PMSG pfn; 函数指针
};
消息一般重新cWnd的虚函数
实现宏中的开始消息
#define BEGIN_TEMPLATE_MESSAGE_MAP(theClass, type_name, baseClass)\
PTM_WARNING_DISABLE\
template < typename type_name >\
const AFX_MSGMAP* theClass< type_name >::GetMessageMap() const\
{ return GetThisMessageMap(); }\
template < typename type_name >\
const AFX_MSGMAP* PASCAL theClass< type_name >::GetThisMessageMap()\
{\
typedef theClass< type_name > ThisClass;\
typedef baseClass TheBaseClass;\
__pragma(warning(push))\
__pragma(warning(disable: 4640)) /* message maps can only be called by single threaded message pump */ \
static const AFX_MSGMAP_ENTRY _messageEntries[] =\
{
实现宏中的结束消息
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
__pragma(warning(pop))\
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
PTM_WARNING_RESTORE
函数指针公用体
union MessageMapFunctions
{
AFX_PMSG pfn; // generic member function pointer
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_D)(CDC*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_b)(BOOL);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_u)(UINT);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_h)(HANDLE);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_u_u)(CWnd*, UINT, UINT);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_W_COPYDATASTRUCT)(CWnd*, COPYDATASTRUCT*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfn_b_HELPINFO)(LPHELPINFO);
HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_W_u)(CDC*, CWnd*, UINT);
HBRUSH (AFX_MSG_CALL CCmdTarget::*pfn_B_D_u)(CDC*, UINT);
int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_W_u)(UINT, CWnd*, UINT);
int (AFX_MSG_CALL CCmdTarget::*pfn_i_u_u)(UINT, UINT);
int (AFX_MSG_CALL CCmdTarget::*pfn_i_W_u_u)(CWnd*, UINT, UINT);
int (AFX_MSG_CALL CWnd::*pfn_i_s)(LPTSTR);
int (AFX_MSG_CALL CWnd::*pfn_i_S)(LPCTSTR);
LRESULT (AFX_MSG_CALL CWnd::*pfn_l_w_l)(WPARAM, LPARAM);
LRESULT (AFX_MSG_CALL CWnd::*pfn_l_u_u_M)(UINT, UINT, CMenu*);
void (AFX_MSG_CALL CWnd::*pfn_v_b_h)(BOOL, HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_v_h)(HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_v_h_h)(HANDLE,HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_v_v)();
int (AFX_MSG_CALL CWnd::*pfn_i_u)(UINT);
HCURSOR (AFX_MSG_CALL CWnd::*pfn_C_v)();
UINT (AFX_MSG_CALL CWnd::*pfn_u_u)(UINT);
BOOL (AFX_MSG_CALL CWnd::*pfn_b_v)();
void (AFX_MSG_CALL CWnd::*pfn_v_u)(UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_up)(UINT_PTR);
void (AFX_MSG_CALL CWnd::*pfn_v_u_u)(UINT, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_i_i)(int, int);
void (AFX_MSG_CALL CWnd::*pfn_v_u_u_u)(UINT, UINT, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_u_i_i)(UINT, int, int);
void (AFX_MSG_CALL CWnd::*pfn_v_w_l)(WPARAM, LPARAM);
void (AFX_MSG_CALL CWnd::*pfn_v_b_W_W)(BOOL, CWnd*, CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_v_D)(CDC*);
void (AFX_MSG_CALL CWnd::*pfn_v_M)(CMenu*);
void (AFX_MSG_CALL CWnd::*pfn_v_M_u_b)(CMenu*, UINT, BOOL);
void (AFX_MSG_CALL CWnd::*pfn_v_W)(CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_v_W_u_u)(CWnd*, UINT, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_W_p)(CWnd*, CPoint);
void (AFX_MSG_CALL CWnd::*pfn_v_W_h)(CWnd*, HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_v_u_W)(UINT, CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_v_u_W_b)(UINT, CWnd*, BOOL);
void (AFX_MSG_CALL CWnd::*pfn_v_u_u_W)(UINT, UINT, CWnd*);
void (AFX_MSG_CALL CWnd::*pfn_v_s)(LPTSTR);
void (AFX_MSG_CALL CWnd::*pfn_v_u_cs)(UINT, LPCTSTR);
void (AFX_MSG_CALL CWnd::*pfn_v_i_s)(int, LPTSTR);
int (AFX_MSG_CALL CWnd::*pfn_i_i_s)(int, LPTSTR);
UINT (AFX_MSG_CALL CWnd::*pfn_u_p)(CPoint);
LRESULT (AFX_MSG_CALL CWnd::*pfn_l_p)(CPoint);
UINT (AFX_MSG_CALL CWnd::*pfn_u_v)();
void (AFX_MSG_CALL CWnd::*pfn_v_b_NCCALCSIZEPARAMS)(BOOL, NCCALCSIZE_PARAMS*);
void (AFX_MSG_CALL CWnd::*pfn_v_v_WINDOWPOS)(WINDOWPOS*);
void (AFX_MSG_CALL CWnd::*pfn_v_u_u_M)(UINT, UINT, HMENU);
void (AFX_MSG_CALL CWnd::*pfn_v_u_p)(UINT, CPoint);
void (AFX_MSG_CALL CWnd::*pfn_v_u_pr)(UINT, LPRECT);
BOOL (AFX_MSG_CALL CWnd::*pfn_b_u_s_p)(UINT, short, CPoint);
void (AFX_MSG_CALL CWnd::*pfn_MOUSEHWHEEL)(UINT, short, CPoint);
LRESULT (AFX_MSG_CALL CWnd::*pfn_l_v)();
UINT (AFX_MSG_CALL CWnd::*pfn_u_W_u)(CWnd*, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_u_M)(UINT, CMenu*);
UINT (AFX_MSG_CALL CWnd::*pfn_u_u_M)(UINT, CMenu*);
UINT (AFX_MSG_CALL CWnd::*pfn_u_v_MENUGETOBJECTINFO)(MENUGETOBJECTINFO*);
void (AFX_MSG_CALL CWnd::*pfn_v_M_u)(CMenu*, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_u_LPMDINEXTMENU)(UINT, LPMDINEXTMENU);
void (AFX_MSG_CALL CWnd::*pfn_APPCOMMAND)(CWnd*, UINT, UINT, UINT);
BOOL (AFX_MSG_CALL CWnd::*pfn_RAWINPUT)(UINT, HRAWINPUT);
UINT (AFX_MSG_CALL CWnd::*pfn_u_u_u)(UINT, UINT);
UINT (AFX_MSG_CALL CWnd::*pfn_u_u_l)(UINT, LPARAM);
void (AFX_MSG_CALL CWnd::*pfn_MOUSE_XBUTTON)(UINT, UINT, CPoint);
void (AFX_MSG_CALL CWnd::*pfn_MOUSE_NCXBUTTON)(short, UINT, CPoint);
void (AFX_MSG_CALL CWnd::*pfn_INPUTLANGCHANGE)(UINT, UINT);
BOOL (AFX_MSG_CALL CWnd::*pfn_v_u_h)(UINT, HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_INPUTDEVICECHANGE)(unsigned short, HANDLE);
LRESULT (AFX_MSG_CALL CWnd::*pfn_l_D_u)(CDC*, UINT);
void (AFX_MSG_CALL CWnd::*pfn_v_F_b)(CFont*, BOOL);
HANDLE (AFX_MSG_CALL CWnd::*pfn_h_v)();
HANDLE (AFX_MSG_CALL CWnd::*pfn_h_b_h)(BOOL, HANDLE);
BOOL (AFX_MSG_CALL CWnd::*pfn_b_v_ii)(int, int);
HANDLE (AFX_MSG_CALL CWnd::*pfn_h_h_h)(HANDLE, HANDLE);
void (AFX_MSG_CALL CWnd::*pfn_v_W_b)(CWnd*, BOOL);
// type safe variant for thread messages
void (AFX_MSG_CALL CWinThread::*pfn_THREAD)(WPARAM, LPARAM);
// specific type safe variants for WM_COMMAND and WM_NOTIFY messages
void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_v)();
BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_v)();
void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_u)(UINT);
BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_u)(UINT);
void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_NMHDR_pl)(NMHDR*, LRESULT*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_NMHDR_pl)(NMHDR*, LRESULT*);
void (AFX_MSG_CALL CCmdTarget::*pfnNotify_v_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfnNotify_b_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*);
void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C)(CCmdUI*);
void (AFX_MSG_CALL CCmdTarget::*pfnCmdUI_v_C_u)(CCmdUI*, UINT);
void (AFX_MSG_CALL CCmdTarget::*pfnCmd_v_pv)(void*);
BOOL (AFX_MSG_CALL CCmdTarget::*pfnCmd_b_pv)(void*);
};
下面是部分的消息 在afxmsg.cpp中的267行 太多了 截取一点做列子
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_COMMAND_RANGE(id, idLast, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_RANGE, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT) > \
(memberFxn)) },
// ON_COMMAND_RANGE(id, idLast, OnBar) is the same as
// ON_CONTROL_RANGE(0, id, idLast, OnBar)
#define ON_COMMAND_EX(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT) > \
(memberFxn)) },
#define ON_COMMAND_EX_RANGE(id, idLast, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)idLast, AfxSigCmd_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT) > \
(memberFxn)) },
// update ui's are listed as WM_COMMAND's so they get routed like commands
#define ON_UPDATE_COMMAND_UI(id, memberFxn) \
{ WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)id, AfxSigCmdUI, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \
(memberFxn)) },
#define ON_UPDATE_COMMAND_UI_RANGE(id, idLast, memberFxn) \
{ WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)idLast, AfxSigCmdUI, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \
(memberFxn)) },
#define ON_NOTIFY(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \
(memberFxn)) },
#define ON_NOTIFY_RANGE(wNotifyCode, id, idLast, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)idLast, AfxSigNotify_RANGE, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
#define ON_NOTIFY_EX(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
#define ON_NOTIFY_EX_RANGE(wNotifyCode, id, idLast, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)idLast, AfxSigNotify_EX, \
(AFX_PMSG) \
(static_cast< BOOL (AFX_MSG_CALL CCmdTarget::*)(UINT, NMHDR*, LRESULT*) > \
(memberFxn)) },
BOOL CCmdTarget::OnCmdMsg(WPARAM wParam, LPARAM lParam) { //遍历消息映射表,查找对应ID的处理函数 AFX_MSGMAP* pMsgmap = GetMessagemap(); //从子类的消息映射表开始,向上逐表查询 while(pMsgmap != NULL) { // 查表 AFXMSG_ENTRY* pEntries = pMsgmap->pEntries; for(int i = 0; pEntries[i].nSig != AfxSig_end; ++i) { if(pEntries[i].nId == LOWORD(wParam)) { MessageFunctions mmf; mmf.pfn_v_v = pEntries[i].pfn; LRESULT lResult = 0; switch(pEntries[i].nSig) { case AfxSig_v_v: { (this->*pEntries[i].pfn)(); break; } case AfxSig_v_iii: { (this->*mmf.pfn_v_iii)(wParam, LOWORD(lParam), HIWORD(lParam)); break; } case AfxSig_v_ii: { (this->*mmf.pfn_v_ii)(LOWORD(lParam), HIWORD(lParam)); break; } case AfxSig_i_p: { lResult = (this->*mmf.pfn_v_p)((LPCREATESTRUCT)lParam); break; } } return TRUE; } } pMsgmap = pMsgmap->pBaseMsgMap; } return FALSE; }