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;
}

 

  

 

posted @ 2020-09-04 20:00  特权E5  阅读(354)  评论(0编辑  收藏  举报