Windows消息机制详解-5
一、 什么是消息
在解釋什么是消息之前,我們先討論一下程序的執行機制問題。大體上說,程序按照執行機制可以分為兩類:
第一類是過程驅動。比如我們最早接觸編程時寫的C程序,又或者單片機程序。這類程序往往預先已經設定好了執行流程,我們執行時只是按部就班的執行;
第二類是事件驅動。事件,相信大家都能夠理解。每個事件的發生都是隨機的,每個事件都會有發生的時刻,類似生活中的事件。程序中的事件也會有自己的觸發點,事件驅動程序就是事先編寫好了針對每個事件的處理流程。在Windows的操作系統中,消息就是Windows中的事件。Windows中的幾乎每個操作都會觸發消息,像我們之前講過的創建窗口會觸發WM_CREATE消息,繪制窗口會觸發WM_PAINT消息,我們點擊鼠標、鍵盤、都會觸發相應的消息。
Windows的消息被封裝成了一個叫做MSG的結構體,其原型如下:
| 1 2 3 4 5 6 7 8 | typedef struct tagMSG { // msg HWND hwnd; UINT message; WPARAM wParam; LPARAM lParam; DWORD time; POINT pt; } MSG; |
Hwnd —— 觸發消息的窗口的句柄。
Message —— 消息ID。Windows操作系統為每個消息都分配了一個消息ID,這個ID是唯一的。我們在上文中提到過的WM_CREATE本質就是一個整數,就是消息ID。
wParam —— 消息可附帶的參數。
lParam —— 消息可附帶的參數。
Time —— 發生消息的時刻。
Pt —— 發生消息時鼠標所在的位置。
以上參數對消息來說,缺一不可。
Windows中就是將一個個消息封裝成MSG對象,發送消息時,將這些對象放置到消息隊列中;獲取消息時,也是獲取的這些MSG對象。
二、 消息獲取
2.1 消息隊列
我們說過,在Windows中幾乎每個操作都會觸發一條消息,這些消息都被發送到消息隊列中。何為消息隊列?我們可以將其理解為使用了一個存放Msg對象的先進先出的Deque—— Deque<Msg>。消息隊列分為兩種,一種是系統消息隊列,另外一種是進程消息隊列。我們在觸發消息后,消息先進入系統消息隊列。操作系統處理后會根據消息的的窗口句柄hwnd值將消息分配到我們程序自己的消息隊列,然后在我們程序內部進行消息的處理。
2.2 消息循環
在前面的文章中,我們曾經寫過一個消息循環。所謂的消息循環,就是不斷的讀取我們的進程中的消息隊里中的消息,然后在進行處理。
| 1 2 3 4 5 6 7 8 9 | void Message()? {? ????MSG nMsg = { 0 };? ????while (GetMessage(&nMsg, NULL, 0, 0))? ????{? ????????TranslateMessage(&nMsg);? ????????DispatchMessage(&nMsg);? ????}? } |
這里面,GetMessage()不斷的在消息隊列中抓取消息,其函數原型如下:
GetMessage(LPMSG lpMsg,HWND hWnd,UINT wMsgFilterMin,UINT wMsgFilterMax)
lpMsg —— 用來存放消息的MSG類型的指針。
hWnd —— 指定取得其消息的窗口的句柄。當其值取NULL時,GetMessage為任何屬于調用線程的窗口檢索消息。
wMsgFilterMin —— 指定被檢索的最小消息值的整數。
wMsgFilterMax —— 指定被檢索的最大消息值的整數。
GetMessage()獲取到消息后,TranslateMessage會將消息進行翻譯,主要是把虛擬鍵消息轉換為字符消息。字符消息被寄送到調用線程的消息隊列里,當下一次線程調用函數GetMessage或PeekMessage時被讀出。Windows中每一個鍵盤按鍵,都對應了一個宏,這個鍵盤按鍵發出的消息就是虛擬鍵消息。TranslateMessage的作用就是將虛擬鍵消息轉成字符消息WM_CHAR、WM_SYSCHAR等等。
三、消息處理
DispatchMessage的作用就是將消息,分派到我們實現定義好的窗口處理函數中進行處理,下面是我們在之前的文章中定義的窗口處理函數:
| 1 2 3 4 5 6 7 8 9 10 11 12 | LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)? {? ????switch (uMsg)? ????{? ????case WM_DESTROY:? ????????PostQuitMessage(0);//可¨|以°?使o1GetMessage返¤|ì回?0? ????????break;? ????default:? ????????break;? ????}? ????return DefWindowProc(hWnd, uMsg, wParam, lParam);? } |
hWnd就是產生消息的窗口句柄,uMsg是傳遞的消息,wParam和lParam分別是消息攜帶的兩個參數。在上面的窗口處理函數中,我們定只處理了一個消息WM_DESTROY,這是我們在點擊窗口的關閉按鈕后產生的一個消息。我們說過,我們在創建窗口是,也會產生一個WM_CREATE消息。下面我們在窗口處理函數中處理這個消息:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)? {? ????switch (uMsg)? ????{? ????case WM_DESTROY:? ????????PostQuitMessage(0);//可¨|以°?使o1GetMessage返¤|ì回?0? ????????break; ????case? WM_CREATE: ????????MessageBox(NULL,"WM_CREATE消息被處理了","消息處理",MB_OK); ????default:? ????????break;? ????}? ????return DefWindowProc(hWnd, uMsg, wParam, lParam);? } |
我們在接受到WM_CREATE后,會彈出一個對話框。預期的效果是點擊這個對話框的確定按鈕后才會顯示窗口。如下面所示:
運行程序,先彈出對話框:
點擊確定按鈕后,彈出窗口:
以上就是Win32 SDK關于Windows消息機制的詳解(圖)的詳細內容
參考:windows運維-PHP中文網?
總結
以上是生活随笔為你收集整理的Windows消息机制详解-5的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: jquery checkbox 选中、
- 下一篇: Windows句柄-2