首頁 > 運維 > windows維 > 主體

Win32 SDK基礎(十一)之訊息佇列與GetMessage/PeekMessage、SendMessage/Postmesage的詳解

黄舟
發布: 2017-06-06 10:09:43
原創
5772 人瀏覽過

一、訊息佇列

1.1 訊息佇列

        訊息佇列是用來存放訊息的一個佇列,訊息在佇列中先入先出,所有的視窗程式都具有訊息佇列,程式可以從佇列中取得訊息。

1.2 訊息佇列的類型

        系統訊息佇列:由作業系統維護的訊息佇列,存放系統產生的訊息,如滑鼠、鍵盤訊息等等。

        程式訊息佇列:屬於每個應用程式(執行緒)的訊息佇列,並以應用程式維護。

        當產生滑鼠、鍵盤等訊息時,訊息先存放到系統訊息佇列,然後作業系統根據儲存的訊息找到對應的視窗的訊息佇列,將訊息投遞到視窗的訊息佇列中。

1.3 佇列訊息與非佇列訊息

        佇列訊息:訊息發出後,先放入佇列,然後透過訊息循環取得。常見的隊列訊息:鍵盤、滑鼠、計時器訊息等等。

        非佇列訊息:訊息發出後,直接找到視窗的訊息處理函數,呼叫訊息處理函數處理,無需經過訊息佇列。常見的非佇列訊息:WM_PAINT、WM_SIZE等等。

二、訊息循環與GetMessage/PeekMessage

2.1 訊息循環

        一般的訊息循環如下:

void Message(HWND hWnd)  
{  
	MSG nMsg = { 0 };
	while (GetMessage(&nMsg, hWnd, 0, 0))  
	{  
		TranslateMessage(&nMsg);  
		DispatchMessage(&nMsg);  

		if(nMsg.message == WM_PAINT)
		{
			char buff[30]={};
			sprintf(buff,"处理消息%d\n",nMsg.message);
			WriteConsole(hOutput,buff,sizeof(buff),NULL,NULL);
		}
	}  
}
登入後複製

GetMessage/PeekMessage:從程式的訊息隊列當中獲取訊息。

TranslateMessage:將鍵盤上的按鍵等訊息翻譯成字元訊息。 

DispatchMessage:將翻譯後的訊息再次放入程式的訊息佇列中。

2.2 GetMessage和PeekMessage

GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
)
登入後複製

lpMsg:指向MSG結構的指針,該結構從線程的訊息佇列裡接收訊息訊息。
hWnd:取得其訊息的視窗的句柄。當其值取NULL時,GetMessage為任何屬於呼叫執行緒的視窗檢索訊息,執行緒訊息透過PostThreadMessage寄送給呼叫執行緒。
wMsgFilterMin:指定被檢索的最小訊息值的整數
wMsgFilterMax:指定被檢索的最大訊息值的整數。
傳回值:如果函數取得WM_QUIT以外的其他訊息,則傳回非零值。如果函數取得WM_QUIT訊息,則傳回值是零。如果出現了錯誤,回傳值是-1。例如,當hWnd是無效的視窗句柄或lpMsg是無效的指標。若想獲得更多的錯誤訊息,請呼叫GetLastError函數。

BOOL PeekMessage(
LPMSG IpMsg,
HWND hWnd,
UINT wMSGfilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
登入後複製

lpMsg:接收訊息訊息的MSG結構指標。
hWnd:其訊息被檢查的視窗句柄。
wMsgFilterMin:指定被檢查的訊息範圍裡的第一個訊息。
wMsgFilterMax:指定被檢查的訊息範圍裡的最後一個訊息。
wRemoveMsg:確定訊息如何被處理。此參數可選擇下列值之一:

意義

#PM_NOREMOVE

PeekMessage處理後,訊息不會從佇列中除掉。

PM_REMOVE

#PeekMessage處理後,訊息從佇列中除掉。

PM_NOYIELD

#此標誌可讓系統不釋放等待呼叫程式空閒的執行緒。可將PM_NOYIELD隨意組合到PM_NOREMOVE或PM_REMOVE。

#


GetMessage和PeekMessage的主要区别在于:GetMessage是阻塞函数,它会在消息循环中会一直阻塞直到消息队列中出现了消息可以被获取,而PeekMessage是非阻塞函数,不管有没有获取到消息队列中的消息,它都会返回。PeekMessage更多用来检测消息队里中是否有消息,它的最后一个参数可以用来指定获取到消息后要不要把消息从消息队列中移除,通常情况下通过PeekMessage检测到消息队列有消息之后,再调用GetMessage区获取。

2.3 GetMessage/PeekMessage获取消息的过程

1、先在程序的消息队列中查找消息,如果有队列消息,就取出消息。

2、如果程序的消息队列中没有消息,向系统的消息队列获取属于本程序的消息。如果系统的消息队列中有属于本程序的消息,系统的消息队列会将消息分发到本程序的消息队列中。

3、如果系统的消息队列也没有消息,检查窗口需要绘制的区域是否需要重绘,如果发现有需要重绘的区域,产生WM_PAINT消息。

4、如果没有重新绘制区域,检查是否具有到时的定时器,如果有产生WM_TIMER定时器消息。

5、如果没有到时的定时器,整理程序的资源、内存等等。

三、SendMessage和PostMessage

LRESULT SendMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM IParam
)
登入後複製

hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。

返回值:返回值指定消息处理的结果,依赖于所发送的消息。

BOOL WINAPI PostMessage(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
登入後複製

hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:
HWND_BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、 被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口
NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样
Msg:指定被寄送的消息。
wParam:指定附加的消息特定的信息。
LParam:指定附加的消息特定的信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零

1、SendMessage

       发送消息到指定的窗口,并等候对方将消息处理,为阻塞函数,获取消息的执行结果后返回。主要需要发送非队列消息,发送的消息不经过消息队列。

2、PostMessage

        发送消息到程序的消息队列,不管消息有没有被处理都会立即返回,用于队列消息的发送

以上是Win32 SDK基礎(十一)之訊息佇列與GetMessage/PeekMessage、SendMessage/Postmesage的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板