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);
voidAFXAPIAfxHookWindowCreate(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;
}
鉤子的執行緒函式
LRESULTCALLBACK
_AfxCbtFilterHook(intcode, WPARAMwParam, LPARAMlParam)
{
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
CWnd* pWndInit = pThreadState->m_pWndInit;
HWNDhWnd = (HWND)wParam;
WNDPROColdWndProc;
if(pWndInit != NULL)
{
AFX_MANAGE_STATE(pWndInit->m_pModuleState);
// 將訊息和控制代碼對應起來
pWndInit->Attach(hWnd);
//允許先進行其他子類化
pWndInit->PreSubclassWindow();
// 用標準子類化視窗AfxWndProc
WNDPROCafxWndProc = AfxGetAfxWndProc();
設定視窗過程函式
oldWndProc = (WNDPROC)SetWindowLongPtr(hWnd, GWLP_WNDPROC,(DWORD_PTR)afxWndProc);
if(oldWndProc != afxWndProc)
*pOldWndProc = oldWndProc;
pThreadState->m_pWndInit = NULL;
}
returnCallNextHookEx(pThreadState->m_hHookOldCbtFilter, code,
}
BOOLCWnd::Attach(HWNDhWndNew)
{
if(hWndNew== NULL)
returnFALSE;
、、如果不存在,建立對映
CHandleMap* pMap = afxMapHWND(TRUE);
新增對映
pMap->SetPermanent(m_hWnd = hWndNew, this);
AttachControlSite(pMap);
returnTRUE;
}
CHandleMap* PASCALafxMapHWND(BOOLbCreate)
{
AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
returnpState->m_pmapHWND;
}
LRESULTCALLBACKAfxWndProc(HWNDhWnd, UINTnMsg, WPARAMwParam, LPARAMlParam)
{
、、所有其他訊息都通過訊息對映路由
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
returnAfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
}
CWnd* PASCALCWnd::FromHandlePermanent(HWNDhWnd)
{
查表,獲得對應的CWND*
CHandleMap* pMap = afxMapHWND();
pWnd = (CWnd*)pMap->LookupPermanent(hWnd);
returnpWnd;
}
voidAFXAPI_AfxTraceMsg(LPCTSTRlpszPrefix, constMSG* pMsg)
{
訊息查表
constAFX_MAP_MESSAGE* pMapMsg = allMessages;
for(/*null*/; pMapMsg->lpszMsg != NULL; pMapMsg++)
{
if(pMapMsg->nMsg == pMsg->message)
{
lpszMsgName = pMapMsg->lpszMsg;
break;
}
}
LRESULTAFXAPIAfxCallWndProc(CWnd* pWnd, HWNDhWnd, UINTnMsg,
WPARAMwParam= 0, LPARAMlParam= 0)
{
獲取執行緒狀態
_AFX_THREAD_STATE* pThreadState = _afxThreadState.GetData();
儲存訊息 巢狀
MSGoldState = 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.
LRESULTlResult;
呼叫WindowProc回撥函式
lResult = pWnd->WindowProc(nMsg, wParam, lParam);
pThreadState->m_lastSentMsg =oldState;
returnlResult;
}
LRESULTCWnd::WindowProc(UINTmessage, WPARAMwParam, LPARAMlParam)
{
// 這裡面呼叫查詢進入對應的訊息入口
LRESULTlResult = 0;
if(!OnWndMsg(message, wParam, lParam, &lResult))
lResult = DefWindowProc(message, wParam, lParam);
returnlResult;
}
BOOLCWnd::OnWndMsg(UINTmessage, WPARAMwParam, LPARAMlParam, LRESULT* pResult)
這個函式中判定了訊息的種類和呼叫不同的對應函式
查對應函式入口
太多了做個標號在 wincore.cpp 中的第2279行
然後在調對應的函式
structAFX_MAP_MESSAGE
{
UINTnMsg;
LPCSTRlpszMsg;
};
訊息定義
staticconstAFX_MAP_MESSAGEallMessages[] =
{
DEFINE_MESSAGE(WM_CREATE),
DEFINE_MESSAGE(WM_DESTROY),
·············
DEFINE_MESSAGE(WM_DEVICECHANGE),
{ 0, NULL, } // end of message list
};
#defineDECLARE_MESSAGE_MAP() \
protected: \
staticconstAFX_MSGMAP* PASCALGetThisMessageMap(); \
virtualconstAFX_MSGMAP* GetMessageMap() const; \
structAFX_MSGMAP
{
基類指標
constAFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
自己的訊息資訊
constAFX_MSGMAP_ENTRY* lpEntries;
};
structAFX_MSGMAP_ENTRY
{
UINTnMessage;
UINTnCode; windows訊息
UINTnID; 控制元件ID(或0用於windows訊息)
UINTnLastID; 用於指定控制元件id範圍的條目
UINT_PTRnSig; 指向訊息的指標型別標誌
AFX_PMSGpfn; 函式指標
};
訊息一般重新cWnd的虛擬函式
實現巨集中的開始訊息
#defineBEGIN_TEMPLATE_MESSAGE_MAP(theClass, type_name, baseClass)\
PTM_WARNING_DISABLE\
template< typenametype_name >\
constAFX_MSGMAP* theClass< type_name >::GetMessageMap() const\
{ returnGetThisMessageMap(); }\
template< typenametype_name >\
constAFX_MSGMAP* PASCALtheClass< type_name >::GetThisMessageMap()\
{\
typedeftheClass< type_name > ThisClass;\
typedefbaseClass TheBaseClass;\
__pragma(warning(push))\
__pragma(warning(disable: 4640)) /* message maps can only be called by single threaded message pump */\
staticconstAFX_MSGMAP_ENTRY _messageEntries[] =\
{
實現巨集中的結束訊息
#defineEND_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
__pragma(warning(pop))\
staticconstAFX_MSGMAPmessageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return&messageMap; \
}\
PTM_WARNING_RESTORE
函式指標公用體
unionMessageMapFunctions
{
AFX_PMSGpfn; // generic member function pointer
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_D)(CDC*);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_b)(BOOL);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_u)(UINT);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_h)(HANDLE);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_W_u_u)(CWnd*, UINT, UINT);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_W_COPYDATASTRUCT)(CWnd*, COPYDATASTRUCT*);
BOOL(AFX_MSG_CALLCCmdTarget::*pfn_b_HELPINFO)(LPHELPINFO);
HBRUSH(AFX_MSG_CALLCCmdTarget::*pfn_B_D_W_u)(CDC*, CWnd*, UINT);
HBRUSH(AFX_MSG_CALLCCmdTarget::*pfn_B_D_u)(CDC*, UINT);
int(AFX_MSG_CALLCCmdTarget::*pfn_i_u_W_u)(UINT, CWnd*, UINT);
int(AFX_MSG_CALLCCmdTarget::*pfn_i_u_u)(UINT, UINT);
int(AFX_MSG_CALLCCmdTarget::*pfn_i_W_u_u)(CWnd*, UINT, UINT);
int(AFX_MSG_CALLCWnd::*pfn_i_s)(LPTSTR);
int(AFX_MSG_CALLCWnd::*pfn_i_S)(LPCTSTR);
LRESULT(AFX_MSG_CALLCWnd::*pfn_l_w_l)(WPARAM, LPARAM);
LRESULT(AFX_MSG_CALLCWnd::*pfn_l_u_u_M)(UINT, UINT, CMenu*);
void(AFX_MSG_CALLCWnd::*pfn_v_b_h)(BOOL, HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_v_h)(HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_v_h_h)(HANDLE,HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_v_v)();
int(AFX_MSG_CALLCWnd::*pfn_i_u)(UINT);
HCURSOR(AFX_MSG_CALLCWnd::*pfn_C_v)();
UINT(AFX_MSG_CALLCWnd::*pfn_u_u)(UINT);
BOOL(AFX_MSG_CALLCWnd::*pfn_b_v)();
void(AFX_MSG_CALLCWnd::*pfn_v_u)(UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_up)(UINT_PTR);
void(AFX_MSG_CALLCWnd::*pfn_v_u_u)(UINT, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_i_i)(int, int);
void(AFX_MSG_CALLCWnd::*pfn_v_u_u_u)(UINT, UINT, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_u_i_i)(UINT, int, int);
void(AFX_MSG_CALLCWnd::*pfn_v_w_l)(WPARAM, LPARAM);
void(AFX_MSG_CALLCWnd::*pfn_v_b_W_W)(BOOL, CWnd*, CWnd*);
void(AFX_MSG_CALLCWnd::*pfn_v_D)(CDC*);
void(AFX_MSG_CALLCWnd::*pfn_v_M)(CMenu*);
void(AFX_MSG_CALLCWnd::*pfn_v_M_u_b)(CMenu*, UINT, BOOL);
void(AFX_MSG_CALLCWnd::*pfn_v_W)(CWnd*);
void(AFX_MSG_CALLCWnd::*pfn_v_W_u_u)(CWnd*, UINT, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_W_p)(CWnd*, CPoint);
void(AFX_MSG_CALLCWnd::*pfn_v_W_h)(CWnd*, HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_v_u_W)(UINT, CWnd*);
void(AFX_MSG_CALLCWnd::*pfn_v_u_W_b)(UINT, CWnd*, BOOL);
void(AFX_MSG_CALLCWnd::*pfn_v_u_u_W)(UINT, UINT, CWnd*);
void(AFX_MSG_CALLCWnd::*pfn_v_s)(LPTSTR);
void(AFX_MSG_CALLCWnd::*pfn_v_u_cs)(UINT, LPCTSTR);
void(AFX_MSG_CALLCWnd::*pfn_v_i_s)(int, LPTSTR);
int(AFX_MSG_CALLCWnd::*pfn_i_i_s)(int, LPTSTR);
UINT(AFX_MSG_CALLCWnd::*pfn_u_p)(CPoint);
LRESULT(AFX_MSG_CALLCWnd::*pfn_l_p)(CPoint);
UINT(AFX_MSG_CALLCWnd::*pfn_u_v)();
void(AFX_MSG_CALLCWnd::*pfn_v_b_NCCALCSIZEPARAMS)(BOOL, NCCALCSIZE_PARAMS*);
void(AFX_MSG_CALLCWnd::*pfn_v_v_WINDOWPOS)(WINDOWPOS*);
void(AFX_MSG_CALLCWnd::*pfn_v_u_u_M)(UINT, UINT, HMENU);
void(AFX_MSG_CALLCWnd::*pfn_v_u_p)(UINT, CPoint);
void(AFX_MSG_CALLCWnd::*pfn_v_u_pr)(UINT, LPRECT);
BOOL(AFX_MSG_CALLCWnd::*pfn_b_u_s_p)(UINT, short, CPoint);
void(AFX_MSG_CALLCWnd::*pfn_MOUSEHWHEEL)(UINT, short, CPoint);
LRESULT(AFX_MSG_CALLCWnd::*pfn_l_v)();
UINT(AFX_MSG_CALLCWnd::*pfn_u_W_u)(CWnd*, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_u_M)(UINT, CMenu*);
UINT(AFX_MSG_CALLCWnd::*pfn_u_u_M)(UINT, CMenu*);
UINT(AFX_MSG_CALLCWnd::*pfn_u_v_MENUGETOBJECTINFO)(MENUGETOBJECTINFO*);
void(AFX_MSG_CALLCWnd::*pfn_v_M_u)(CMenu*, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_u_LPMDINEXTMENU)(UINT, LPMDINEXTMENU);
void(AFX_MSG_CALLCWnd::*pfn_APPCOMMAND)(CWnd*, UINT, UINT, UINT);
BOOL(AFX_MSG_CALLCWnd::*pfn_RAWINPUT)(UINT, HRAWINPUT);
UINT(AFX_MSG_CALLCWnd::*pfn_u_u_u)(UINT, UINT);
UINT(AFX_MSG_CALLCWnd::*pfn_u_u_l)(UINT, LPARAM);
void(AFX_MSG_CALLCWnd::*pfn_MOUSE_XBUTTON)(UINT, UINT, CPoint);
void(AFX_MSG_CALLCWnd::*pfn_MOUSE_NCXBUTTON)(short, UINT, CPoint);
void(AFX_MSG_CALLCWnd::*pfn_INPUTLANGCHANGE)(UINT, UINT);
BOOL(AFX_MSG_CALLCWnd::*pfn_v_u_h)(UINT, HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_INPUTDEVICECHANGE)(unsignedshort, HANDLE);
LRESULT(AFX_MSG_CALLCWnd::*pfn_l_D_u)(CDC*, UINT);
void(AFX_MSG_CALLCWnd::*pfn_v_F_b)(CFont*, BOOL);
HANDLE(AFX_MSG_CALLCWnd::*pfn_h_v)();
HANDLE(AFX_MSG_CALLCWnd::*pfn_h_b_h)(BOOL, HANDLE);
BOOL(AFX_MSG_CALLCWnd::*pfn_b_v_ii)(int, int);
HANDLE(AFX_MSG_CALLCWnd::*pfn_h_h_h)(HANDLE, HANDLE);
void(AFX_MSG_CALLCWnd::*pfn_v_W_b)(CWnd*, BOOL);
// type safe variant for thread messages
void(AFX_MSG_CALLCWinThread::*pfn_THREAD)(WPARAM, LPARAM);
// specific type safe variants for WM_COMMAND and WM_NOTIFY messages
void(AFX_MSG_CALLCCmdTarget::*pfnCmd_v_v)();
BOOL(AFX_MSG_CALLCCmdTarget::*pfnCmd_b_v)();
void(AFX_MSG_CALLCCmdTarget::*pfnCmd_v_u)(UINT);
BOOL(AFX_MSG_CALLCCmdTarget::*pfnCmd_b_u)(UINT);
void(AFX_MSG_CALLCCmdTarget::*pfnNotify_v_NMHDR_pl)(NMHDR*, LRESULT*);
BOOL(AFX_MSG_CALLCCmdTarget::*pfnNotify_b_NMHDR_pl)(NMHDR*, LRESULT*);
void(AFX_MSG_CALLCCmdTarget::*pfnNotify_v_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*);
BOOL(AFX_MSG_CALLCCmdTarget::*pfnNotify_b_u_NMHDR_pl)(UINT, NMHDR*, LRESULT*);
void(AFX_MSG_CALLCCmdTarget::*pfnCmdUI_v_C)(CCmdUI*);
void(AFX_MSG_CALLCCmdTarget::*pfnCmdUI_v_C_u)(CCmdUI*, UINT);
void(AFX_MSG_CALLCCmdTarget::*pfnCmd_v_pv)(void*);
BOOL(AFX_MSG_CALLCCmdTarget::*pfnCmd_b_pv)(void*);
};
下面是部分的訊息 在afxmsg.cpp中的267行 太多了 擷取一點做列子
#defineON_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)
#defineON_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)
#defineON_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)) },
#defineON_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
#defineON_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)) },
#defineON_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)) },
#defineON_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)) },
#defineON_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)) },
#defineON_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)) },
#defineON_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)) },