1. 程式人生 > 實用技巧 >MFC 訊息機制

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)) },