青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

saga's blog

突出重點,系統全面,不留死角

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

公告

QQ:34O859O5

常用鏈接

留言簿(15)

搜索

  •  

積分與排名

  • 積分 - 212858
  • 排名 - 124

最新評論

閱讀排行榜

評論排行榜

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

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

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

程序開始時候,會是main函數,然后會生成初始的窗口,同時會調用WndProc函數.這是一個自定義的函數,名字也會有變化,但其功能是一樣的,就是運行消息分流器.WndProc函數如下:

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

//......

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

}

這其中,hwnd是窗口的句柄,msg是系統發送來的消息的名字.wParam和lParam則是隨消息一起發送來的消息參數.

WndProc函數使用了消息分流器,下面把消息分流器的內容解釋一下:

一重,當不同的消息出現時,在其中寫入相應的程序語句即可。
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);
}

二重,運用三個消息分流器進行處理。
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的消息分流器就是這樣的模樣。
它的本質就是宏定義。
其中的四個參數有三個都是從本函數的入口參數中直接得到的,即為hwnd, wParam, lParam。
只有第四的參數是表明調用的函數。
消息分流器是在winowsx.h文件中定義的。由此,可以看出第四個參數是調用的函數,其定義如下:

#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類型的變量,其數值為0。
int類型時,可在后面加l或者L(小寫和大寫形式)
表明無符號數時,可在后面加u或者U(小寫和大寫形式)
float類型時,可在后面加f或者F(小寫和大寫形式)
例如:
128u 1024UL 1L 8Lu 3.14159F 0.1f

LRESULT是一個系統的數據類型,其定義如下:
typedef LONG_PTR LRESULT;

LONG_PTR也是一個系統的數據類型,其定義如下:
#if defined(_WIN64)
 typedef __int64 LONG_PTR;
#else
 typedef long LONG_PTR;
#endif
由此可見,LRESULT的實質就是64的long類型的變量

那么(LRESULT)-1L的實質并不是減法,而是((LRESULT)(-1L)),即強制類型轉換

三重,把消息分流器的宏定義代換回去,就成了下面的樣子
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應返回TRUE,導致WndProc返回0,否則Cls_OnCreate返回FALSE,導致WndProc返回-1;

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

  case WM_DESTROY:
  return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
 }
 return DefWindowProc(hwnd, msg, wParam, lParam);
}
在逗號表達式,C++會計算每個表達式,但完整的逗號表達式的結果是最右邊表達式的值。
所以,會return 0。
然后,就可以手動的編寫各個處理函數了: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也是一個宏,它在windowsx.h中定義,如下:
#define HANDLE_MSG(hwnd, message, fn) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

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

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

以上四重,是消息分離器的基本使用,但,這不完整,消息分離器主要應用在對話框消息處理中。
這里,窗口子類化是我們經常使用的手段,這也可以通過消息分流器實現,

第五重
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,以表明,如果沒有約定響應的消息,
則返回父親窗口false,如果有,則返回ture,這是與前四重不同的地方。
一般情況下,對話框過程函數應該在處理了消息的情況下返回TRUE,如果沒有處理,則返回FALSE。
如果對話框過程返回了FALSE,那么對話框管理器為這條消息準備默認的對話操作。

但是,這其中有錯誤,因為有的消息,需要單獨處理。單獨處理的消息列表見SetDlgMsgResult宏。

第六重
這點小問題,這就需要用到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;
}
這里,就用直接用到了第二重的消息分流器,而拋棄了其他。

這個宏定義如下:
#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)
)

為了表述清楚,所以用了此格式,這是一個三項表達式,首先對消息類型進行考察。

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

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

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

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是牛人定義的一個宏,它把case也包含進來了。
#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 閱讀(1727) 評論(2)  編輯 收藏 引用 所屬分類: 轉的貼

Feedback

# re: [轉載]windows消息分流器 2007-12-19 09:32 秦歌
還是不太明白  回復  更多評論
  

# re: [轉載]windows消息分流器 2009-07-15 16:09 郭偉
不錯  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产一区美女| 久久精品国产精品亚洲| 国产一区自拍视频| 日韩一级大片| 亚洲精品视频免费在线观看| 久久精品在线| 91久久精品美女高潮| 亚洲第一精品在线| 亚洲色诱最新| 欧美成人精品一区| 美女精品一区| 欧美日产国产成人免费图片| 欧美日韩成人在线视频| 欧美日韩无遮挡| 国产精品日产欧美久久久久| 亚洲欧美日韩天堂一区二区| 亚洲一区二区在线播放| 亚洲综合激情| 老巨人导航500精品| 亚洲国产日韩欧美在线动漫| 在线一区日本视频| 久久久九九九九| 欧美日本精品在线| 国产日产欧美一区| 亚洲日韩视频| 久久国产精品99久久久久久老狼| 免费一级欧美片在线播放| 日韩视频一区二区在线观看 | 久久www免费人成看片高清| 欧美影视一区| 欧美激情黄色片| 欧美淫片网站| 国产精品国色综合久久| 久久综合激情| 欧美午夜宅男影院| 亚洲高清激情| 欧美中在线观看| 亚洲免费精品| 卡一卡二国产精品| 国产女精品视频网站免费| 亚洲国产高清一区| 免费观看成人| 欧美一区二区日韩一区二区| 欧美日韩国产美| 亚洲精品一区在线观看| 亚洲大片在线| 亚洲一二三四久久| 亚洲精品中文字| 国产精品mv在线观看| 欧美一区国产在线| 久久精品一区蜜桃臀影院| 在线观看视频亚洲| 99v久久综合狠狠综合久久| 国产一区二区三区奇米久涩| 99在线热播精品免费| 亚洲欧美变态国产另类| 欧美久久综合| 久久国产66| 欧美性色综合| 亚洲午夜电影网| 亚洲精品久久在线| 欧美电影在线观看完整版| 樱桃视频在线观看一区| 久久人人爽人人爽| 久久精品一区二区三区不卡| 韩国成人精品a∨在线观看| 久久九九全国免费精品观看| 欧美一级片一区| 狠狠色伊人亚洲综合成人| 久久精品欧美日韩精品| 欧美在线观看www| 激情视频一区| 欧美激情一区三区| 欧美精品一区视频| 亚洲免费婷婷| 欧美一级片久久久久久久| 韩国久久久久| 亚洲国产精品一区二区三区| 欧美日本乱大交xxxxx| 亚洲男人影院| 久久精品免费| 亚洲精品影视在线观看| 一本色道久久加勒比88综合| 国产欧美日韩另类视频免费观看| 久久久亚洲高清| 欧美成ee人免费视频| 亚洲一级网站| 久久久久.com| 亚洲天堂av电影| 欧美一区二区啪啪| 亚洲免费激情| 亚洲欧美日韩视频二区| 亚洲国产精品一区二区第四页av| 亚洲激情在线观看| 国产九区一区在线| 欧美激情精品久久久久久黑人 | 欧美影院成人| 亚洲国产合集| 欧美日韩色综合| 欧美一级淫片aaaaaaa视频| 久久久成人网| 中日韩美女免费视频网址在线观看| 午夜视频在线观看一区二区| 亚洲精品一区二区三| 午夜日韩av| 亚洲自拍偷拍视频| 你懂的视频一区二区| 久久国产精品电影| 欧美视频精品在线观看| 免费日韩av片| 国产精一区二区三区| 亚洲精品在线观看视频| 在线免费一区三区| 亚欧成人在线| 欧美亚洲一区在线| 欧美日韩亚洲综合一区| 亚洲大片在线观看| 一区三区视频| 欧美一区二区三区在线看 | 韩日精品中文字幕| 亚洲永久在线观看| 亚洲天堂久久| 欧美国产在线观看| 欧美国产专区| 亚洲二区在线| 欧美在线观看视频在线| 午夜日韩激情| 国产精品久久国产愉拍| 欧美激情精品久久久| 国产一区日韩二区欧美三区| 亚洲综合色激情五月| 欧美成人免费观看| 欧美一区二区三区免费视频| 欧美日韩中文字幕在线视频| 亚洲狼人综合| 亚洲天堂免费观看| 国产精品扒开腿爽爽爽视频 | 久久夜色精品亚洲噜噜国产mv | 亚洲欧美另类中文字幕| 亚洲视频欧美视频| 欧美日韩在线播放一区二区| 亚洲美女中出| 亚洲一区二区三区视频| 欧美午夜国产| 午夜视频在线观看一区| 久久久久免费视频| 在线欧美小视频| 欧美国产三级| 一本色道久久综合亚洲精品小说| 亚洲无线视频| 国产精品自拍在线| 午夜一区在线| 欧美成年人视频| 一区二区高清视频| 国产精品欧美日韩一区二区| 香蕉久久一区二区不卡无毒影院| 狼人天天伊人久久| 亚洲精品乱码视频| 欧美日韩中文字幕在线视频| 亚洲女性喷水在线观看一区| 亚洲一区在线播放| 国产精品一区久久| 久久爱另类一区二区小说| 巨乳诱惑日韩免费av| 亚洲激情国产精品| 欧美~级网站不卡| 99视频一区二区| 久久久久久久久一区二区| 亚洲激情在线播放| 国产精品美女xx| 亚洲国产一区二区三区高清| 99re66热这里只有精品3直播| 国产精品乱码久久久久久| 久久精品亚洲一区| 亚洲毛片在线| 久久亚洲私人国产精品va媚药| 亚洲欧洲日夜超级视频| 国产精品视频一区二区高潮| 久久综合网络一区二区| 一区二区三区欧美亚洲| 久久久久久有精品国产| 一区二区三区蜜桃网| 国产在线视频不卡二| 欧美三级乱码| 久久综合九色综合欧美就去吻| 在线综合欧美| 亚洲国产专区| 免费成人高清| 久久xxxx| 亚洲一区二区在线| 亚洲美女在线一区| 在线高清一区| 国内精品久久久久影院优| 国产精品成人免费| 欧美精品在线免费观看| 久久精品一二三区| 欧美一区二区三区在线播放| 亚洲一级黄色av| 久久精品女人天堂| 亚洲综合日本|