• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            牧光小院

            被約束的日日夜夜,停不下來的時(shí)間。

            MFC漫談(五)——消息的路由(2)

            繼續(xù)上一個(gè)主題



            直線上溯的消息

            上次說到消息被轉(zhuǎn)發(fā)到了AfxWndProc,繼續(xù)。

            LRESULT?CALLBACK
            AfxWndProc(HWND?hWnd,?UINT?nMsg,?WPARAM?wParam,?LPARAM?lParam)?
            {
            ????
            //?…

            ????
            //?all?other?messages?route?through?message?map
            ????CWnd*?pWnd?=?CWnd::FromHandlePermanent(hWnd);
            ????
            //?…
            ????return?AfxCallWndProc(pWnd,?hWnd,?nMsg,?wParam,?lParam);
            }


            LRESULT?AFXAPI?AfxCallWndProc(CWnd
            *?pWnd,?HWND?hWnd,?UINT?nMsg,
            ????????????????????????WPARAM?wParam?
            =?0,?LPARAM?lParam?=?0)?{
            ????
            //?…
            ????
            //?Catch?exceptions?thrown?outside?the?scope?of?a?callback
            ????
            //?in?debug?builds?and?warn?the?user.
            ????LRESULT?lResult;
            ????
            //?…
            ????
            //?delegate?to?object's?WindowProc
            ????lResult?=?pWnd->WindowProc(nMsg,?wParam,?lParam);
            ????
            //?…
            ????return?lResult;
            }

            最后,消息被傳到了WindowProc中,這是一個(gè)CWnd類中的虛函數(shù),而MFC則通過虛函數(shù)機(jī)制把消息的處理直接轉(zhuǎn)發(fā)到相應(yīng)窗口的窗口過程(例如CFrameWnd),這里,我們來看CWnd::WndProc

            LRESULT?CWnd::WindowProc(UINT?message,?WPARAM?wParam,?LPARAM?lParam)? {
            ????
            // ?OnWndMsg?does?most?of?the?work,?except?for?DefWindowProc?call
            ????LRESULT?lResult? = ? 0 ;
            ????
            if ?( ! OnWndMsg(message,?wParam,?lParam,? & lResult))
            ????lResult?
            = ?DefWindowProc(message,?wParam,?lParam);
            ????
            return ?lResult;
            }

            首先利用OnWndMsg處理消息,如果OnWndMsg沒能處理消息,調(diào)用DefWindowProc。先來看OnWndMsg,這是一個(gè)CWnd類的虛函數(shù),這個(gè)函數(shù)的邏輯很簡(jiǎn)單,如果消息是WM_COMMAND或WM_NOTIFY,則把消息分別交給OnCommand和OnNotify處理,否則首先在MFC內(nèi)建的消息緩存中查找消息,如果命中但沒有相應(yīng)的處理函數(shù),則返回FALSE(這樣的話會(huì)交由CWnd::DefWindowProc處理),如果命中,則進(jìn)一步判斷是用戶自己注冊(cè)的消息還是標(biāo)準(zhǔn)Windows消息,如果是前者,就跳到標(biāo)LDispatchRegistered處理,調(diào)用相應(yīng)的消息處理函數(shù),否則就跳到LDispatch處理,調(diào)用正確的消息處理函數(shù)。

            如果消息不在緩存中,那么就沿著某個(gè)類的繼承路線,由AfxFindMessageEntry在每一個(gè)類的消息映射表中查找,如果找到匹配項(xiàng),同樣按照是否是用戶注冊(cè)的消息的邏輯對(duì)消息進(jìn)行處理,如果始終沒有找到匹配項(xiàng),則返回FALSE,交由CWnd::DefWindowProc處理。

            BOOL?CWnd::OnWndMsg(UINT?message,?WPARAM?wParam,?LPARAM?lParam,?LRESULT * ?pResult)
            {
            ????
            //
            ?
            ????
            // ?special?case?for?commands

            ???? if ?(message? == ?WM_COMMAND)
            ????
            {
            ????????
            if ?(OnCommand(wParam,?lParam))?? // ?對(duì)WM_COMMAND交給OnCommand處理

            ???????? {
            ????????????lResult?
            = ? 1
            ;
            ????????????
            goto
            ?LReturnTrue;
            ????????}

            ????????
            return ?FALSE;
            ????}


            ????
            // ?special?case?for?notifies
            ???? if ?(message? == ?WM_NOTIFY)
            ????
            {
            ????????NMHDR
            * ?pNMHDR? = ?(NMHDR *
            )lParam;
            ????????
            if ?(pNMHDR -> hwndFrom? != ?NULL? && ?OnNotify(wParam,?lParam,? &
            lResult))
            ????????????
            goto
            ?LReturnTrue;
            ????????
            return
            ?FALSE;
            ????}

            ????
            // ?…?…
            ???? const ?AFX_MSGMAP * ?pMessageMap;?pMessageMap? = ?GetMessageMap();? // ?獲取類的消息映射表
            ????
            // ?

            ????AFX_MSG_CACHE * ?pMsgCache;?
            ????pMsgCache?
            = ? &
            _afxMsgCache[iHash];
            ????
            const ?AFX_MSGMAP_ENTRY *
            ?lpEntry;
            ????
            // ?判斷消息是否在緩存中

            ???? if ?(message? == ?pMsgCache -> nMsg? && ?pMessageMap? == ?pMsgCache -> pMessageMap)? {
            ????????
            // ?cache?hit

            ????????lpEntry? = ?pMsgCache -> lpEntry;
            ????????AfxUnlockGlobals(CRIT_WINMSGCACHE);
            ????????
            if ?(lpEntry? == ?NULL)? // ?在緩存中,但是沒有相應(yīng)的表項(xiàng),返回FALSE

            ???????? return ?FALSE;

            ????????
            // ?cache?hit,?and?it?needs?to?be?handled

            ???????? if ?(message? < ? 0xC000 )? // ?否則,按照是否是用戶自定義的消息,?跳轉(zhuǎn)到相應(yīng)的位置
            ???????????? goto ?LDispatch;? // ?標(biāo)準(zhǔn)Windows消息
            ???????? else
            ????????????
            goto ?LDispatchRegistered;? // ?用戶自定義消息
            ????}

            ????
            else ? // ?如果消息不在緩存中,就只好挨家挨戶檢查一番
            ???? {
            ????????
            // ?not?in?cache,?look?for?it

            ????????pMsgCache -> nMsg? = ?message;
            ????????pMsgCache
            -> pMessageMap? =
            ?pMessageMap;
            ????????
            // ?下面這個(gè)for循環(huán)從派生類到基類檢查每一個(gè)類的消息映射表

            ???????? for ?( /* ?pMessageMap?already?init'ed? */ ;?pMessageMap? != ?NULL;
            ????????????pMessageMap?
            = ?pMessageMap -> pBaseMap)??
            {
            ????????????
            if ?(message? < ? 0xC000 )? // ?如果消息是Windows標(biāo)準(zhǔn)消息

            ???????????? {
            ????????????????
            // ?constant?window?message

            ???????????????? if ?((lpEntry? = ?AfxFindMessageEntry(pMessageMap -> lpEntries,
            ????????????????message,?
            0 ,? 0 ))? != ?NULL)?
            {
            ????????????????????pMsgCache
            -> lpEntry? =
            ?lpEntry;
            ????????????????????AfxUnlockGlobals(CRIT_WINMSGCACHE);
            ????????????????????
            goto ?LDispatch;? // ?如果找到對(duì)應(yīng)項(xiàng),就轉(zhuǎn)去處理

            ????????????????}

            ????????????}

            ????????????
            else ? // ?如果是用戶自定義消息
            ???????????? {
            ????????????????
            // ?registered?windows?message

            ????????????????lpEntry? = ?pMessageMap -> lpEntries;
            ????????????????
            while ?((lpEntry? = ?AfxFindMessageEntry(lpEntry,? 0xC000 ,? 0 ,? 0 ))? !=
            ?NULL)
            ????????????????
            {
            ????????????????????UINT
            * ?pnID? = ?(UINT * )(lpEntry ->
            nSig);
            ????????????????????ASSERT(
            * pnID? >= ? 0xC000 ? || ? * pnID? == ? 0
            );
            ????????????????????
            // ?must?be?successfully?registered

            ???????????????????? if ?( * pnID? == ?message)
            ????????????????????
            {
            ????????????????????????pMsgCache
            -> lpEntry? =
            ?lpEntry;
            ????????????????????????AfxUnlockGlobals(CRIT_WINMSGCACHE);
            ????????????????????????
            goto ?LDispatchRegistered;? // ?如果找到就轉(zhuǎn)去處理

            ????????????????????}

            ????????????????????????lpEntry
            ++ ;?????? // ?keep?looking?past?this?one
            ????????????????}

            ????????????}

            ????????}

            ????????
            // ?即不在緩存中,所有的類也都對(duì)此消息置之不理,那么就返回FALSE,交由CWnd::DefWndProc
            ????????
            // ?處理

            ????????pMsgCache -> lpEntry? = ?NULL;
            ????????AfxUnlockGlobals(CRIT_WINMSGCACHE);
            ????????
            return
            ?FALSE;
            ????}

            ????
            // ?下面是對(duì)Windows標(biāo)準(zhǔn)消息和用戶自定義消息的處理
            LDispatch:
            ????ASSERT(message?
            < ? 0xC000
            );

            ????mmf.pfn?
            = ?lpEntry ->
            pfn;

            ????
            switch ?(lpEntry ->
            nSig)
            ????
            {
            ????
            default
            :
            ????????ASSERT(FALSE);
            ????????
            break
            ;

            ????
            case
            ?AfxSig_b_D_v:
            ????????lResult?
            = ?( this ->* mmf.pfn_b_D)(CDC::FromHandle(reinterpret_cast < HDC >
            (wParam)));
            ????????
            break
            ;

            ????
            case
            ?AfxSig_b_b_v:
            ????????lResult?
            = ?( this ->* mmf.pfn_b_b)(static_cast < BOOL >
            (wParam));
            ????????
            break
            ;

            ????
            case
            ?AfxSig_b_u_v:
            ????????lResult?
            = ?( this ->* mmf.pfn_b_u)(static_cast < UINT >
            (wParam));
            ????????
            break
            ;

            ????
            case
            ?AfxSig_b_h_v:
            ????????lResult?
            = ?( this ->* mmf.pfn_b_h)(reinterpret_cast < HANDLE >
            (wParam));
            ????????
            break
            ;
            ????????
            // ?…?…

            ????}

            ?
            goto ?LReturnTrue;
            LDispatchRegistered:????
            // ?for?registered?windows?messages

            ????ASSERT(message? >= ? 0xC000 );
            ????ASSERT(
            sizeof (mmf)? == ? sizeof
            (mmf.pfn));
            ????mmf.pfn?
            = ?lpEntry ->
            pfn;
            ????lResult?
            = ?( this ->*
            mmf.pfn_l_w_l)(wParam,?lParam);

            LReturnTrue:
            ????
            if ?(pResult? !=
            ?NULL)
            ?????
            * pResult? =
            ?lResult;
            ????
            return
            ?TRUE;
            }

            寫到這里,對(duì)于直線上溯的消息的處理過程,應(yīng)該是很清楚了,概括一下,就是先準(zhǔn)備好兩個(gè)處理過程,一個(gè)用來處理標(biāo)準(zhǔn)Windows消息,一個(gè)用來處理用戶自定義消息,之后,根據(jù)消息是不是在緩存中,進(jìn)行不同的查找,如果找到,根據(jù)消息的類型轉(zhuǎn)到不同的處理過程中去,如果處理過了,就返回TRUE,否則返回FALSE,交由CWnd::DefWindowProc處理。到此,關(guān)于直線上溯消息的處理就結(jié)束了,很簡(jiǎn)單,無非就是從派生類到基類的一個(gè)比較操作,真正復(fù)雜些的是MFC對(duì)于WM_COMMAND消息的處理,我們后面再說了。

            posted on 2006-05-19 09:08 nacci 閱讀(4653) 評(píng)論(3)  編輯 收藏 引用 所屬分類: C++漫談

            評(píng)論

            # re: MFC漫談(五)——消息的路由(2) 2006-09-05 11:21 lll

            11  回復(fù)  更多評(píng)論   

            # re: MFC漫談(五)——消息的路由(2) 2007-10-11 16:05 seamonst

            全明了。非常感謝!
            期待對(duì)OnCommand的進(jìn)一步分析。  回復(fù)  更多評(píng)論   

            # re: MFC漫談(五)——消息的路由(2)[未登錄] 2008-07-08 15:03 sky

            very good! thanks! Up!  回復(fù)  更多評(píng)論   

            <2006年5月>
            30123456
            78910111213
            14151617181920
            21222324252627
            28293031123
            45678910

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(2)

            隨筆分類

            收藏夾

            大家的聲音

            積分與排名

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久黄片| 久久综合给合久久国产免费| 久久精品国产久精国产果冻传媒| 久久久久久国产精品无码下载| 久久精品亚洲精品国产色婷| 国产福利电影一区二区三区,免费久久久久久久精 | 久久一区二区三区免费| 人人妻久久人人澡人人爽人人精品| 色狠狠久久AV五月综合| 天天久久狠狠色综合| 久久天天躁夜夜躁狠狠| 91精品日韩人妻无码久久不卡 | 日韩久久无码免费毛片软件| 少妇高潮惨叫久久久久久| 国产精品一区二区久久精品无码| 国产aⅴ激情无码久久| 国产精品成人99久久久久 | 无码国内精品久久综合88| 久久精品成人免费网站| 久久午夜无码鲁丝片秋霞| 一级做a爱片久久毛片| 亚洲精品tv久久久久久久久| 久久久久亚洲?V成人无码| 久久久久亚洲Av无码专| 欧美久久天天综合香蕉伊| 2021精品国产综合久久| 狠狠综合久久综合88亚洲| 久久91这里精品国产2020| 99久久精品国内| 97久久国产综合精品女不卡| 久久激情五月丁香伊人| 精品久久久久久中文字幕| 精品国产乱码久久久久久人妻| 久久99精品国产麻豆婷婷| 国产成人精品白浆久久69| 久久天天躁狠狠躁夜夜avapp | 亚洲午夜无码AV毛片久久| 日本久久久精品中文字幕| 国内精品久久久久久99蜜桃| 欧美亚洲国产精品久久高清| 久久福利片|