首頁  >  文章  >  運維  >  Win32 SDK基礎(八)之 關於Windows訊息機制的詳解(圖)

Win32 SDK基礎(八)之 關於Windows訊息機制的詳解(圖)

黄舟
黄舟原創
2017-06-06 10:02:153979瀏覽

一、 什麼是訊息

        在解釋什麼是訊息之前,我們先討論程式的執行機制問題。大體上說,程式依照執行機制可以分為兩類:
第一類是過程驅動。例如我們最早接觸程式時寫的C程序,又或者單晶片程式。這類程序往往預先已經設定好了執行流程,我們執行時只是按部就班的執行;
第二類是事件驅動。事件,相信大家都能夠理解。每個事件的發生都是隨機的,每個事件都會有發生的時刻,類似生活中的事件。程式中的事件也會有自己的觸發點,事件驅動程式就是事先編寫好了針對每個事件的處理流程。在Windows的作業系統中,訊息就是Windows中的事件。 Windows中的幾乎每個操作都會觸發訊息,像我們之前講過的建立視窗會觸發WM_CREATE訊息,繪製視窗會觸發WM_PAINT訊息,我們點擊滑鼠、鍵盤、都會觸發對應的訊息。
        Windows的訊息被封裝成了一個叫做MSG的結構體,其原型如下:

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—— Dequeaee932e3af002b763748cf2e999e819c。訊息佇列分為兩種,一種是系統訊息佇列,另外一種是進程訊息佇列。我們在觸發訊息後,訊息先進入系統訊息佇列。作業系統處理後會根據訊息的的視窗句柄hwnd值將訊息分配到我們程式自己的訊息佇列,然後在我們程式內部進行訊息的處理。

2.2 訊息循環

        在前面的文章中,我們曾經寫過一個訊息循環。所謂的訊息循環,就是不斷的讀取我們的進程中的消息隊裡的消息,然後在進行處理。

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的作用是將訊息,分派到我們實現定義好的視窗處理函數中處理,以下是我們在之前的文章中定義的視窗處理函數:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
{  
	switch (uMsg)  
	{  
	case WM_DESTROY:  
		PostQuitMessage(0);//可¨¦以°?使º1GetMessage返¤¦Ì回?0  
		break;  
	default:  
		break;  
	}  
	return DefWindowProc(hWnd, uMsg, wParam, lParam);  
}


        hWnd就是产生消息的窗口句柄,uMsg是传递的消息,wParam和lParam分别是消息携带的两个参数。在上面的窗口处理函数中,我们定只处理了一个消息WM_DESTROY,这是我们在点击窗口的关闭按钮后产生的一个消息。我们说过,我们在创建窗口是,也会产生一个WM_CREATE消息。下面我们在窗口处理函数中处理这个消息:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)  
{  
	switch (uMsg)  
	{  
	case WM_DESTROY:  
		PostQuitMessage(0);//可¨¦以°?使º1GetMessage返¤¦Ì回?0  
		break; 
	case  WM_CREATE:
		MessageBox(NULL,"WM_CREATE消息被处理了","消息处理",MB_OK);
	default:  
		break;  
	}  
	return DefWindowProc(hWnd, uMsg, wParam, lParam);  
}


        我们在接受到WM_CREATE后,会弹出一个对话框。预期的效果是点击这个对话框的确定按钮后才会显示窗口。如下面所示:

        运行程序,先弹出对话框:


        点击确定按钮后,弹出窗口:


以上是Win32 SDK基礎(八)之 關於Windows訊息機制的詳解(圖)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn