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

            saga's blog

            突出重點(diǎn),系統(tǒng)全面,不留死角

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              33 Posts :: 2 Stories :: 185 Comments :: 0 Trackbacks

            公告

            QQ:34O859O5

            常用鏈接

            留言簿(15)

            搜索

            •  

            積分與排名

            • 積分 - 210877
            • 排名 - 122

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            **轉(zhuǎn)載**
            自己看核心編程,對(duì)消息分流器不太理解,這篇寫的不錯(cuò),所以轉(zhuǎn)載。
            文章作者:欣欣
            原文鏈接:http://blog.csdn.net/hopkins9961629/archive/2006/01/25/588184.aspx

            很好理解,windows操作系統(tǒng)使用消息處理機(jī)制,那么,我們所設(shè)計(jì)的程序如何才能分辨和處理系統(tǒng)中的各種消息呢?這就是消息分流器的作用.

            簡單來說,消息分流器就是一段代碼,在我的講述中,將分7重來循序漸進(jìn)的介紹它.從最初的第1重到最成熟的第7重,它的樣子會(huì)有很大的變化.但,實(shí)現(xiàn)的功能都是一樣的,所不同的,僅僅是變得更加簡練罷了.

            程序開始時(shí)候,會(huì)是main函數(shù),然后會(huì)生成初始的窗口,同時(shí)會(huì)調(diào)用WndProc函數(shù).這是一個(gè)自定義的函數(shù),名字也會(huì)有變化,但其功能是一樣的,就是運(yùn)行消息分流器.WndProc函數(shù)如下:

            LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
            {

            //......

            return DefWindowProc(hwnd, msg, wParam, lParam);

            }

            這其中,hwnd是窗口的句柄,msg是系統(tǒng)發(fā)送來的消息的名字.wParam和lParam則是隨消息一起發(fā)送來的消息參數(shù).

            WndProc函數(shù)使用了消息分流器,下面把消息分流器的內(nèi)容解釋一下:

            一重,當(dāng)不同的消息出現(xiàn)時(shí),在其中寫入相應(yīng)的程序語句即可。
            LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
              case WM_CREATE:
              // ...
              return 0;

              case WM_PAINT:
              // ...
              return 0;

              case WM_DESTROY:
              //...
              return 0;
             }
             return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            二重,運(yùn)用三個(gè)消息分流器進(jìn)行處理。
            LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
              case WM_CREATE:
              return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);

              case WM_PAINT:
              return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);

              case WM_DESTROY:
              return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);
             }
             return DefWindowProc(hwnd, msg, wParam, lParam);
            }
            這里的HANDLE_WM_CREATE,HANDLE_WM_PAINT,HANDLE_WM_DESTROY就是消息分流器。
            與消息不同之處就是在前面增加了“HANDLE_”字符,windows的消息分流器就是這樣的模樣。
            它的本質(zhì)就是宏定義。
            其中的四個(gè)參數(shù)有三個(gè)都是從本函數(shù)的入口參數(shù)中直接得到的,即為hwnd, wParam, lParam。
            只有第四的參數(shù)是表明調(diào)用的函數(shù)。
            消息分流器是在winowsx.h文件中定義的。由此,可以看出第四個(gè)參數(shù)是調(diào)用的函數(shù),其定義如下:

            #define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) ((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)

            #define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

            #define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

            0L是表示int類型的變量,其數(shù)值為0。
            int類型時(shí),可在后面加l或者L(小寫和大寫形式)
            表明無符號(hào)數(shù)時(shí),可在后面加u或者U(小寫和大寫形式)
            float類型時(shí),可在后面加f或者F(小寫和大寫形式)
            例如:
            128u 1024UL 1L 8Lu 3.14159F 0.1f

            LRESULT是一個(gè)系統(tǒng)的數(shù)據(jù)類型,其定義如下:
            typedef LONG_PTR LRESULT;

            LONG_PTR也是一個(gè)系統(tǒng)的數(shù)據(jù)類型,其定義如下:
            #if defined(_WIN64)
             typedef __int64 LONG_PTR;
            #else
             typedef long LONG_PTR;
            #endif
            由此可見,LRESULT的實(shí)質(zhì)就是64的long類型的變量

            那么(LRESULT)-1L的實(shí)質(zhì)并不是減法,而是((LRESULT)(-1L)),即強(qiáng)制類型轉(zhuǎn)換

            三重,把消息分流器的宏定義代換回去,就成了下面的樣子
            LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
              case WM_CREATE:
              return Cls_OnCreate(hwnd, (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L;
              // 如果處理了消息,則Cls_OnCreate應(yīng)返回TRUE,導(dǎo)致WndProc返回0,否則Cls_OnCreate返回FALSE,導(dǎo)致WndProc返回-1;

              case WM_PAINT:
              return Cls_OnPaint(hwnd), 0L;
              // 逗號(hào)表達(dá)式;Cls_OnPaint是void類型,這里返回0;

              case WM_DESTROY:
              return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
             }
             return DefWindowProc(hwnd, msg, wParam, lParam);
            }
            在逗號(hào)表達(dá)式,C++會(huì)計(jì)算每個(gè)表達(dá)式,但完整的逗號(hào)表達(dá)式的結(jié)果是最右邊表達(dá)式的值。
            所以,會(huì)return 0。
            然后,就可以手動(dòng)的編寫各個(gè)處理函數(shù)了:Cls_OnCreate,Cls_OnPaint,WM_DESTROY。

            四重,
            LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
              HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
              HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
              HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
             }
             return DefWindowProc(hwnd, msg, wParam, lParam);
            }

            HANDLE_MSG也是一個(gè)宏,它在windowsx.h中定義,如下:
            #define HANDLE_MSG(hwnd, message, fn) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

            這個(gè)宏要做的就是根據(jù)不同的message(##用來連接前后的字符串),把自己“變成”相應(yīng)的HANDLE_XXXXMESSAGE形式的宏,再通過相應(yīng)的宏來執(zhí)行消息處理代碼。
            說白了,就是把message的消息做為替換,##就是一個(gè)替換的標(biāo)志。
            如果沒有##,就成了HANDLE_message了,這樣,宏是不會(huì)被代換的。
            如果就單獨(dú)一個(gè),則會(huì)代換,如hwnd和fn。

            比如實(shí)際代碼中寫入:
            HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)
            則經(jīng)過轉(zhuǎn)換就變成:
            case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))
            這與二重一模一樣。

            以上四重,是消息分離器的基本使用,但,這不完整,消息分離器主要應(yīng)用在對(duì)話框消息處理中。
            這里,窗口子類化是我們經(jīng)常使用的手段,這也可以通過消息分流器實(shí)現(xiàn),

            第五重
            LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
              HANDLE_MSG(hwnd, WM_INITDIALO , Cls_OnInitDialog); // 不能直接使用HANDLE_MSG宏
              HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG宏
             }
             return false;
            }
            由于是窗口子類化,所以,最后,返回的是false,以表明,如果沒有約定響應(yīng)的消息,
            則返回父親窗口false,如果有,則返回ture,這是與前四重不同的地方。
            一般情況下,對(duì)話框過程函數(shù)應(yīng)該在處理了消息的情況下返回TRUE,如果沒有處理,則返回FALSE。
            如果對(duì)話框過程返回了FALSE,那么對(duì)話框管理器為這條消息準(zhǔn)備默認(rèn)的對(duì)話操作。

            但是,這其中有錯(cuò)誤,因?yàn)橛械南?需要單獨(dú)處理。單獨(dú)處理的消息列表見SetDlgMsgResult宏。

            第六重
            這點(diǎn)小問題,這就需要用到SetDlgMsgResult(hwnd, msg, result)宏。

            LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
            switch(msg)
             {
             case WM_INITDIALO:
             return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_INITDIALO((hwnd), (wParam), (lParam), (fn)));

             case WM_COMMAND:
             return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (fn)));
             }
            return false;
            }
            這里,就用直接用到了第二重的消息分流器,而拋棄了其他。

            這個(gè)宏定義如下:
            #define SetDlgMsgResult(hwnd, msg, result)
            (
             (
             (msg) == WM_CTLCOLORMSGBOX ||
             (msg) == WM_CTLCOLOREDIT ||
             (msg) == WM_CTLCOLORLISTBOX ||
             (msg) == WM_CTLCOLORBTN ||
             (msg) == WM_CTLCOLORDLG ||
             (msg) == WM_CTLCOLORSCROLLBAR ||
             (msg) == WM_CTLCOLORSTATIC ||
             (msg) == WM_COMPAREITEM ||
             (msg) == WM_VKEYTOITEM ||
             (msg) == WM_CHARTOITEM ||
             (msg) == WM_QUERYDRAGICON ||
             (msg) == WM_INITDIALOG
             ) ?
             (BOOL)(result) :
             (SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE)
            )

            為了表述清楚,所以用了此格式,這是一個(gè)三項(xiàng)表達(dá)式,首先對(duì)消息類型進(jìn)行考察。

            如果對(duì)話框過程處理的消息恰巧為返回特定值中的一個(gè),則如實(shí)返回result;
            不要被前面的BOOL蒙蔽,BOOL在頭文件中的定義實(shí)際上是一個(gè)int型,
            一旦需要返回非TRUE或FALSE的其他值,照樣可以;

            這樣,我們的Cls_OnInitDialog就能夠正確的返回它的BOOL值了,
            而Cls_OnCommand在處理之后,也可以由后面的逗號(hào)表達(dá)式正確的返回一個(gè)TRUE表示消息已處理。

            第七重
            我們還可以把case也包含進(jìn)來,就成了如下的樣子。

            LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
            {
             switch(msg)
             {
             chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog);
             chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);
             }
             return false;
            }

            chHANDLE_DLGMSG是牛人定義的一個(gè)宏,它把case也包含進(jìn)來了。
            #define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

            這樣,程序中的語句
             switch (uMsg)
             {
              chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
              chHANDLE_DLGMSG(hwnd, WM_SIZE,       Dlg_OnSize);
              chHANDLE_DLGMSG(hwnd, WM_COMMAND,    Dlg_OnCommand);
             }

            就被翻譯成:
             switch (uMsg)
             {
             case (WM_INITDIALOG):
              return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_INITDIALOG((hwnd), (wParam), (lParam), (Dlg_OnInitDialog))));

             case (WM_SIZE)
              return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_SIZE((hwnd), (wParam), (lParam), (Dlg_OnSize))));

             case (WM_COMMAND)
              return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (Dlg_OnCommand))));
             }

            這樣,消息分流器,就介紹完畢.

            posted on 2007-09-04 13:40 saga.constantine 閱讀(1695) 評(píng)論(2)  編輯 收藏 引用 所屬分類: 轉(zhuǎn)的貼

            Feedback

            # re: [轉(zhuǎn)載]windows消息分流器 2007-12-19 09:32 秦歌
            還是不太明白  回復(fù)  更多評(píng)論
              

            # re: [轉(zhuǎn)載]windows消息分流器 2009-07-15 16:09 郭偉
            不錯(cuò)  回復(fù)  更多評(píng)論
              

            久久青青草原精品国产软件| 久久综合丁香激情久久| 伊人久久成人成综合网222| 亚洲国产综合久久天堂| 久久精品国产亚洲av高清漫画| 国产精品久久亚洲不卡动漫| 国产精品无码久久四虎| 久久99久国产麻精品66| 久久99亚洲综合精品首页| 久久亚洲AV成人无码软件| 日韩亚洲欧美久久久www综合网 | 狠狠色丁香久久综合婷婷| 中文精品久久久久国产网址| 亚洲午夜久久久久久噜噜噜| 久久国产成人午夜AV影院| 色婷婷综合久久久久中文 | 97精品伊人久久大香线蕉| 久久国产免费观看精品| 波多野结衣AV无码久久一区| 久久久久人妻一区精品果冻| 久久久青草久久久青草| 亚洲国产精品无码久久一区二区| 久久香蕉国产线看观看猫咪?v| 久久精品嫩草影院| 奇米综合四色77777久久| 欧美日韩精品久久免费| 久久精品免费大片国产大片| 久久99国产精品久久久| 97久久国产亚洲精品超碰热| 性欧美大战久久久久久久久| 亚洲性久久久影院| 思思久久好好热精品国产| 久久精品二区| 日本国产精品久久| 开心久久婷婷综合中文字幕| 激情综合色综合久久综合| 国内精品久久久久久麻豆 | 91精品国产综合久久香蕉 | 少妇久久久久久被弄高潮| 久久久久久久波多野结衣高潮| 久久亚洲AV无码精品色午夜麻豆|