zoukankan      html  css  js  c++  java
  • 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;
    }
    

     

      

     

    学如逆水行舟,不进则退。 博客园技术交流群 群 号:1073255314 (本群没人,刚刚建立 -_-!!! )
  • 相关阅读:
    线性分类器之感知机算法
    字符串包含判断
    王家林 云计算分布式大数据Hadoop实战高手之路从零开始 第二讲:全球最详细的从零起步搭建Hadoop单机和伪分布式开发环境图文教程
    王家林 第六讲Hadoop图文训练课程:使用HDFS命令行工具操作Hadoop分布式集群初体验
    王家林的“云计算分布式大数据Hadoop实战高手之路从零开始”的第五讲Hadoop图文训练课程:解决典型Hadoop分布式集群环境搭建问题
    王家林的 第三讲Hadoop图文训练课程:证明Hadoop工作的正确性和可靠性只需4步图文并茂的过程
    王家林 第四讲Hadoop图文训练课程:实战构建真正的Hadoop分布式集群环境
    麻雀GUIv1.0整理好咯,发个开源上来。
    body设置背景色异常
    safari浏览器placeholder垂直居中
  • 原文地址:https://www.cnblogs.com/Mj-NaijAm/p/13615931.html
Copyright © 2011-2022 走看看