• <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>

            牧光小院

            被約束的日日夜夜,停不下來的時間。

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

            繼續(xù)上一個主題



            直線上溯的消息

            上次說到消息被轉(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中,這是一個CWnd類中的虛函數(shù),而MFC則通過虛函數(shù)機制把消息的處理直接轉(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,這是一個CWnd類的虛函數(shù),這個函數(shù)的邏輯很簡單,如果消息是WM_COMMAND或WM_NOTIFY,則把消息分別交給OnCommand和OnNotify處理,否則首先在MFC內(nèi)建的消息緩存中查找消息,如果命中但沒有相應(yīng)的處理函數(shù),則返回FALSE(這樣的話會交由CWnd::DefWindowProc處理),如果命中,則進一步判斷是用戶自己注冊的消息還是標(biāo)準(zhǔn)Windows消息,如果是前者,就跳到標(biāo)LDispatchRegistered處理,調(diào)用相應(yīng)的消息處理函數(shù),否則就跳到LDispatch處理,調(diào)用正確的消息處理函數(shù)。

            如果消息不在緩存中,那么就沿著某個類的繼承路線,由AfxFindMessageEntry在每一個類的消息映射表中查找,如果找到匹配項,同樣按照是否是用戶注冊的消息的邏輯對消息進行處理,如果始終沒有找到匹配項,則返回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))?? // ?對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)的表項,返回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;
            ????????
            // ?下面這個for循環(huán)從派生類到基類檢查每一個類的消息映射表

            ???????? 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;? // ?如果找到對應(yī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
            ????????????????}

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

            ????????}

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

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

            ????
            // ?下面是對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;
            }

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

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

            評論

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

            11  回復(fù)  更多評論   

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

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

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

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

            <2005年11月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            導(dǎo)航

            統(tǒng)計

            常用鏈接

            留言簿(2)

            隨筆分類

            收藏夾

            大家的聲音

            積分與排名

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲国产精品无码久久久久久曰| 国产偷久久久精品专区| 99久久免费只有精品国产| 久久国产V一级毛多内射| 久久免费观看视频| 色婷婷久久综合中文久久蜜桃av| 粉嫩小泬无遮挡久久久久久| 久久人妻少妇嫩草AV无码蜜桃 | 亚洲国产成人久久综合一| 久久久精品国产亚洲成人满18免费网站| 超级碰碰碰碰97久久久久| 热99re久久国超精品首页| 狠狠色丁香久久婷婷综合蜜芽五月| 久久er热视频在这里精品| 久久热这里只有精品在线观看| 精品久久久久久久中文字幕 | 无码人妻久久一区二区三区免费 | 久久线看观看精品香蕉国产| 国产一区二区久久久| 久久精品国产亚洲AV不卡| 国内精品久久久久久野外| 国产精品久久久久久久久久影院| 99久久精品国产一区二区三区| 色偷偷88888欧美精品久久久| 久久亚洲欧洲国产综合| 国产精品久久久久一区二区三区| 久久天堂AV综合合色蜜桃网 | 国产精品久久久久jk制服| 久久强奷乱码老熟女网站| 中文字幕精品久久| 久久亚洲精品无码观看不卡| 久久国产免费直播| 一本伊大人香蕉久久网手机| 69久久精品无码一区二区| 国产色综合久久无码有码| 亚洲精品乱码久久久久久自慰| 性做久久久久久久久浪潮| 久久午夜无码鲁丝片秋霞| 久久婷婷午色综合夜啪| 久久久久久久波多野结衣高潮| 国产激情久久久久久熟女老人 |