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

            旅途

            如果想飛得高,就該把地平線忘掉

            深度剖析消息反射機(jī)制

              摘要:在前面我們分析了控件通知消息WM_NOTIFY,和WM_NOTIFY緊密聯(lián)系的還有一個(gè)MFC新特性:消息反射。本文中,我想就這個(gè)問(wèn)題作一個(gè)全面的論述,如果有錯(cuò)誤,還望各路大蝦批評(píng)指正。

                什么是消息反射?
                在windows里面,子控件經(jīng)常向父控件發(fā)送消息,例如很多子控件要繪制自己的背景,就可能向父窗口發(fā)送消息WM_CTLCOLOR。對(duì)于從子控件發(fā)來(lái)的消息,父控件有可能在處理之前,把消息返還給子控件處理,這樣消息看起來(lái)就想是從父窗口反射回來(lái)一樣,故此得名:消息反射。

                消息反射的由來(lái)
                在windows和MFC4.0版本一下,父窗口(通常是一個(gè)對(duì)話框)會(huì)對(duì)這些消息進(jìn)行處理,換句話說(shuō),自控件的這些消息處理必須在父窗口類體內(nèi),每當(dāng)我們添加子控件的時(shí)候,就要在父窗口類中復(fù)制這些代碼,我們可以想象這是多么的復(fù)雜,代碼是多么的臃腫!
                我們可以想象,如果這些消息都讓父窗口類去做,父窗口就成了一個(gè)萬(wàn)能的神,一個(gè)臃腫不堪的代碼機(jī),無(wú)論如何消息的處理都集中在父窗口類中,會(huì)使父窗口繁重?zé)o比,但是子控件卻無(wú)事可做,并且代碼也無(wú)法重用,這對(duì)于一個(gè)程序員來(lái)講是多么痛苦的一件事?!
                在老版本的MFC中,設(shè)計(jì)者也意識(shí)到了這個(gè)問(wèn)題,他們對(duì)一些消息采用了虛擬機(jī)制,例如:WM_DRAWITEM,這樣子控件就有機(jī)會(huì)控制自己的動(dòng)作,代碼的可重用性有了一定的提高,但是這還沒(méi)有達(dá)到大部分人的要求,所以在高版本的MFC中,提出了一種更方便的機(jī)制:消息反射。
                通過(guò)消息反射機(jī)制,子控件窗口便能夠自行處理與自身相關(guān)的一些消息,增強(qiáng)了封裝性,同時(shí)也提高了子控件窗口類的可重用性。不過(guò)需要注意的是:消息反射是MFC實(shí)現(xiàn)的,不是windows實(shí)現(xiàn)的;要讓你的消息反射機(jī)制工作,你得類必須從CWnd類派生。

                Message-Map中的處理
                如果想要處理消息反射,必須了解相應(yīng)的Message-Map宏和函數(shù)原型。一般來(lái)講,Message-Map是有一定的規(guī)律的,通常她在消息的前面加上一個(gè)ON_ ,然后再消息的最后加上 _REFLECT。例如我們前面提到的WM_CTLCOLOR 經(jīng)過(guò)處理后變成了ON_WM_CTLCOLOR_REFLECT;WM_MEASUREITEM則變成了ON_WM_MEASUREITEM_REFLECT。
                凡事總會(huì)有例外,這里也是這樣,這里面有3個(gè)例外:
                (1) WM_COMMAND 轉(zhuǎn)換成 ON_CONTROL_REFLECT;
                (2) WM_NOTIFY  轉(zhuǎn)換成 ON_NOTIFY_REFLECT;
                (3) ON_UPDATE_COMMAND_UI 轉(zhuǎn)換成 ON_UPDATE_COMMAND_UI_REFLECT;
                對(duì)于函數(shù)原型,也必須是以 afx_msg 開(kāi)頭。

                利用ClassWizard添加消息反射
                (1)在ClassWizard中,打開(kāi)選擇項(xiàng)Message Maps;
                (2)在下拉列表Class name中選擇你要控制的類;
                (3)在Object IDs中,選中相應(yīng)的類名;
                (4)在Messages一欄中找到前面帶有=標(biāo)記的消息,那就是反射消息;
                (5)雙擊鼠標(biāo)或者單擊添加按鈕,然后OK!

                消息處理的過(guò)程
              (1)子窗口向父窗口發(fā)送通知消息,激發(fā)父窗口去調(diào)用它的虛函數(shù)CWnd::OnNotify。大致的結(jié)構(gòu)如下
                   BOOL CWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
                   {
                      if (ReflectLastMsg(hWndCtrl, pResult)) file://hWndCtrl,為發(fā)送窗口
                                                return TRUE; file://如果子窗口已處理了此消息,返回
                      AFX_NOTIFY notify;
                      notify.pResult = pResult;
                      notify.pNMHDR = pNMHDR;
                      return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY)? notify:NULL);
                  }
              (2)ReflectLastMsg聲明如下:static BOOL PASCAL ReflectLastMsg(HWND hWndChild, LRESULT* pResult = NULL);
                 它的主要任務(wù)就是調(diào)用發(fā)送窗口的SendChildNotifyLastMsg。
              (3)SendChildNotifyLastMsg聲明如下:BOOL SendChildNotifyLastMsg(LRESULT* pResult = NULL);
                 調(diào)用發(fā)送窗口的虛函數(shù)OnChildNotify函數(shù),進(jìn)行處理。 如果發(fā)送窗口沒(méi)有進(jìn)行重載處理,則調(diào)用ReflectChildNotify(...)函數(shù)進(jìn)行標(biāo)準(zhǔn)的反射消息的消息映射處理。

                使用的一個(gè)例子
               
            這里面我們舉一個(gè)簡(jiǎn)單的例子,希望大家能夠更清晰的掌握消息反射機(jī)制。
                (1)創(chuàng)建一個(gè)基于對(duì)話框的工程。
                (2)利用向?qū)?chuàng)建一個(gè)新的類:CMyEdit,基類是CEdit。
                (3)在CMyEdit頭文件中加入3個(gè)成員變量:
                     COLORREF m_clrText ;
             COLORREF m_clrBkgnd ;
             CBrush   m_brBkgnd;
                (4)利用向?qū)г谄渲屑尤隬M_CTLCOLOR(看到了么,前面是不是有一個(gè)=?),并且將它的函數(shù)體改為:
                     HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)
                    {
              pDC->SetTextColor( m_clrText );    // text
              pDC->SetBkColor( m_clrBkgnd );    // text bkgnd
              return m_brBkgnd;                // ctl bkgnd
                    }
                    同時(shí)我們?cè)?cpp文件中會(huì)看到ON_WM_CTLCOLOR_REFLECT(),這就是我們所說(shuō)的經(jīng)過(guò)處理的宏,是不是很符合規(guī)則?
                (5)在對(duì)話框中加入一個(gè)Edit,增加一個(gè)關(guān)聯(lián)的變量,選擇Control屬性,類別為CMyEdit。
                (6)在對(duì)話框.cpp文件中加入#include "MyEdit.h",運(yùn)行,看到了什么?呵呵。
               
                 事情到了一個(gè)階段,希望你能夠喜歡,明天見(jiàn)!


            posted on 2007-07-18 15:28 旅途 閱讀(215) 評(píng)論(0)  編輯 收藏 引用 所屬分類: 深入windows

            国产亚洲成人久久| 狠狠色婷婷久久一区二区三区| 精品国产乱码久久久久软件| 久久久91人妻无码精品蜜桃HD| 国产精品久久国产精品99盘 | 久久亚洲AV成人无码电影| 日韩AV毛片精品久久久| 久久人人爽人人精品视频| 国内精品免费久久影院| 久久久久免费视频| 日日狠狠久久偷偷色综合96蜜桃| 久久久久这里只有精品| 亚洲乱码日产精品a级毛片久久| 欧美成a人片免费看久久| 亚洲国产精品成人久久蜜臀| 2021国内久久精品| 激情伊人五月天久久综合| 色综合久久中文色婷婷| 亚洲一级Av无码毛片久久精品| 2021国产精品久久精品| 国产综合久久久久| 久久精品国产亚洲一区二区三区| 欧洲性大片xxxxx久久久| av色综合久久天堂av色综合在| 色偷偷88888欧美精品久久久| 久久这里只精品国产99热| 三级韩国一区久久二区综合| 久久久久久亚洲Av无码精品专口| 久久青青草原国产精品免费| 亚洲欧美国产精品专区久久| www.久久热| 久久精品国产乱子伦| 99久久亚洲综合精品成人| 久久精品日日躁夜夜躁欧美| 99久久成人国产精品免费| 污污内射久久一区二区欧美日韩 | A狠狠久久蜜臀婷色中文网| 四虎影视久久久免费观看| 热久久这里只有精品| 婷婷久久久亚洲欧洲日产国码AV| 国产午夜精品理论片久久|