消息機制

消息機制

Windows消息系統(tǒng)是由以下三部分構成的:
1、消息隊列
2、消息循環(huán)
3、窗口過程

關于消息、窗口過程

一個消息由一個消息名稱(UINT),和兩個參數(shù)(WPARAM,LPARAM)組成。當用戶進行了輸入或是窗口的狀態(tài)發(fā)生改變時系統(tǒng)都會發(fā)送消息到某一個窗口。例如當菜單轉中之后會有WM_COMMAND消息發(fā)送,WPARAM的高字中(HIWORD(wParam))是命令的ID號,對菜單來講就是菜單ID。當然用戶也可以定義自己的消息名稱,也可以利用自定義消息來發(fā)送通知和傳送數(shù)據(jù)。
一個消息必須由一個窗口接收。在窗口的過程(WNDPROC)中可以對消息進行分析,對自己需要的消息進行處理。例如你希望對菜單選擇進行處理那么你可以定義對WM_COMMAND進行處理的代碼,如果希望在窗口中進行圖形輸出就必須對WM_PAINT進行處理。
M$為窗口編寫了默認的窗口過程,這個窗口過程將負責處理那些你不處理消息。正因為有了這個默認窗口過程我們才可以利用Windows的窗口進行開發(fā)而不必過多關注窗口各種消息的處理。例如窗口在被拖動時會有很多消息發(fā)送,而我們都可以不予理睬讓系統(tǒng)自己去處理。

消息分類

消息能夠被分為「隊列化的」和「非隊列化的」。

隊列化的消息是由Windows放入程序消息隊列中的。在程序的消息循環(huán)中,重新傳回并分配給窗口消息處理程序。非隊列化的消息在Windows呼叫窗口時直接送給窗口消息處理程序。也就是說,隊列化的消息被「發(fā)送」給消息隊列,而非隊列化的消息則「發(fā)送」給窗口消息處理程序。任何情況下,窗口消息處理程序都將獲得窗口所有的消息--包括隊列化的和非隊列化的。窗口消息處理程序是窗口的「消息中心」。隊列化消息基本上是使用者輸入的結果,以擊鍵(如WM_KEYDOWN和WM_KEYUP消息)、擊鍵產(chǎn)生的字符(WM_CHAR)、鼠標移動(WM_MOUSEMOVE)和鼠標按鈕(WM_LBUTTONDOWN)的形式給出。隊列化消息還包含時鐘消息(WM_TIMER)、更新消息(WM_PAINT)和退出消息(WM_QUIT)。

非隊列化消息則是其它消息。在許多情況下,非隊列化消息來自呼叫特定的Windows函數(shù)。例如,當WinMain呼叫CreateWindow時,Windows將建立窗口并在處理中給窗口消息處理程序發(fā)送一個WM_CREATE消息。當WinMain呼叫ShowWindow時,Windows將給窗口消息處理程序發(fā)送WM_SIZE和WM_SHOWWINDOW消息。當WinMain呼叫UpdateWindow時,Windows將給窗口消息處理程序發(fā)送WM_PAINT消息。鍵盤或鼠標輸入時發(fā)出的隊列化消息信號,也能在非隊列化消息中出現(xiàn)。例如,用鍵盤或鼠標選擇了一個菜單項時,鍵盤或鼠標消息就是隊列化的,而說明菜單項已選中的WM_COMMAND消息則可能就是非隊列化的。

窗口過程處理消息偽代碼
LONG yourWndProc(HWND hWnd,UINT uMessageType,WPARAM wP,LPARAM)
{
    switch(uMessageType)
    {//使用SWITCH語句將各種消息分開

    case(WM_PAINT):
        doYourWindow(...);//在窗口需要重新繪制時進行輸出
        break;

    case(WM_LBUTTONDOWN):
        doYourWork(...);//在鼠標左鍵被按下時進行處理
        break;

    default:
        callDefaultWndProc(...);//對于其它情況就讓系統(tǒng)自己處理
        break;
    }
}

關于句柄

在windows中,句柄是和對象一一對應的32位無符號整數(shù)值。對象可以映射到唯一的句柄,句柄也可以映射到唯一的對象。句柄是一種內(nèi)部代碼,通過它能引用受系統(tǒng)控制的特殊元素,如窗口、位圖、圖標、內(nèi)存塊、光標、字體、菜單等。
在消息發(fā)送的過程中,有一個很重要的東西就是窗口句柄。系統(tǒng)通過窗口句柄來在整個系統(tǒng)中唯一標識一個窗口,發(fā)送一個消息時必須指定一個窗口句柄表明該消息由那個窗口接收。而每個窗口都會有自己的窗口過程,所以用戶的輸入就會被正確的處理。

消息隊列

消息隊列就是一個消息的鏈表。可以把消息看作一個記錄,具有特定的格式以及特定的優(yōu)先級。對消息隊列有寫權限的進程可以向消息隊列中按照一定的規(guī)則添加新消息;對消息隊列有讀權限的進程則可以從消息隊列中讀走消息。消息隊列是隨內(nèi)核持續(xù)的。
消息隊列(Message Queue),是分布式系統(tǒng)中重要的組件,其通用的使用場景可以簡單地描述為:當不需要立即獲得結果,但是并發(fā)量又需要進行控制的時候,差不多就是需要使用消息隊列的時候。
消息隊列主要解決了應用耦合、異步處理、流量削鋒等問題。當前使用較多的消息隊列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而部分數(shù)據(jù)庫如Redis、Mysql以及phxsql也可實現(xiàn)消息隊列的功能。

附:消息隊列相關介紹

使用消息隊列的十大理由:https://www.oschina.net/translate/top-10-uses-for-message-queue?cmp
消息隊列使用的四種場景介紹:https://blog.csdn.net/seven__________7/article/details/70225830
消息隊列及常見消息隊列介紹:http://baijiahao.baidu.com/s?id=1579988943735023087&wfr=spider&for=pc
再談消息隊列技術:https://www.cnblogs.com/tianqing/p/7110468.html
為什么會需要消息隊列?https://www.cnblogs.com/xuyatao/p/6864109.html

消息循環(huán)

Windows是以消息驅動的操作系統(tǒng),Windows 消息提供了應用程序與Windows系統(tǒng)之間進行通訊的手段。
Windows應用程序是基于消息的程序設計模式,使用事件驅動編程模型,分為消息概述、消息結構、消息類型。

Windows 中有一個系統(tǒng)消息隊列,對于每一個正在執(zhí)行的Windows應用程序,系統(tǒng)為其建立一個“消息隊列”,即應用程序隊列,用來存放該程序可能創(chuàng)建的各種窗口的消息。應用程序中含有一段稱作“消息循環(huán)”的代碼,用來從消息隊列中檢索這些消息并把它們分發(fā)到相應的窗口函數(shù)中。

消息循環(huán)代碼是應用程序中主函數(shù)WinMain ( )中類似如下的程序段:

while(GetMessage(&msg,NULL,0,0))
{ //從消息隊列中取得消息
    TranslateMessage(&msg);    //檢索并生成字符消息WM_CHAR
    DispatchMessage(&msg);    //將消息發(fā)送給相應的窗口函數(shù)
}

由此可見,所謂“消息循環(huán)”,實際是程序循環(huán)。

Windows 應用程序創(chuàng)建的每個窗口都在系統(tǒng)核心注冊一個相應的窗口函數(shù),窗口函數(shù)程序代碼形式上是一個巨大的switch 語句(見上文),用以處理由消息循環(huán)發(fā)送到該窗口的消息,窗口函數(shù)由Windows 采用消息驅動的形式直接調(diào)用,而不是由應用程序顯示調(diào)用的,窗口函數(shù)處理完消息后又將控制權返回給Windows。

小結

一個消息從產(chǎn)生到被一個窗口響應,其中有5個步驟:
1、系統(tǒng)中發(fā)生了某個事件。
2、Windows把這個事件翻譯為消息,然后把它放到消息隊列中。
3、應用程序從消息隊列中接收到這個消息,把它存放在TMsg記錄中。
4、應用程序把消息傳遞給一個適當?shù)拇翱诘拇翱谶^程。
5、窗口過程響應這個消息并進行處理。

步驟3和4構成了應用程序的消息循環(huán)。消息循環(huán)往往是Windows應用程序的核心,因為消息循環(huán)使一個應用程序能夠響應外部的事件。消息循環(huán)的任務就是從消息隊列中檢索消息,然后把消息傳遞給適當?shù)拇翱?。如果消息隊列中沒有消息,Windows就允許其他應用程序處理它們的消息。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容