訊息及訊息佇列,訊息訊息佇列
作業系統將每個事件都封裝成一個稱為訊息的結構體MSG來傳遞給應用程式
typedef struct tagMSG { HWND hwnd; //控制代碼(HANDLE),資源的標識。 UINT message;//無符號的整型 WPARAM wParam;//整型,訊息的附加資訊 LPARAM lParam;//整型,訊息的附加資訊 DWORD time; //32位的整型,訊息傳遞出的時間 POINT pt;//點結構體} MSG;
vc/mfc 進程訊息佇列,線程訊息佇列,與系統訊息佇列,該怎處理
隊列訊息和非隊列訊息
從訊息的發送途徑來看,訊息可以分成2種:隊列訊息和非隊列訊息。訊息佇列由可以分成系統訊息佇列和線程訊息佇列。系統訊息佇列由Windows維護,線程訊息佇列則由每個GUI線程自己進行維護,為避免給non-GUI現成建立訊息佇列,所有線程產生時並沒有訊息佇列,僅當線程第一次調用GDI函數數系統給線程建立一個訊息佇列。隊列訊息送到系統訊息佇列,然後到線程訊息佇列;非隊列訊息直接送給目的視窗過程。
對於隊列訊息,最常見的是滑鼠和鍵盤觸發的訊息,例如WM_MOUSERMOVE,WM_CHAR等訊息,還有一些其它的訊息,例如:WM_PAINT、WM_TIMER和WM_QUIT。當滑鼠、鍵盤事件被觸發後,相應的滑鼠或鍵盤驅動程式就會把這些事件轉換成相應的訊息,然後輸送到系統訊息佇列,由Windows系統去進行處理。Windows系統則在適當的時機,從系統訊息佇列中取出一個訊息,根據前面我們所說的MSG訊息結構確定訊息是要被送往那個視窗,然後把取出的訊息送往建立視窗的線程的相應隊列,下面的事情就該由線程訊息佇列操心了,Windows開始忙自己的事情去了。線程看到自己的訊息佇列中有訊息,就從隊列中取出來,通過作業系統發送到合適的視窗過程去處理。
一般來講,系統總是將訊息Post在訊息佇列的末尾。這樣保證視窗以先進先出的順序接受訊息。然而,WM_PAINT是一個例外,同一個視窗的多個 WM_PAINT被合并成一個 WM_PAINT 訊息, 合并所有的無效地區到一個無效地區。合并WM_PAIN的目的是為了減少重新整理視窗的次數。
非隊列訊息將會繞過系統隊列和訊息佇列,直接將訊息發送到視窗過程,。系統發送非隊列訊息通知視窗,系統發送訊息通知視窗。 例如,當使用者啟用一個視窗系統發送WM_ACTIVATE, WM_SETFOCUS, and WM_SETCURSOR。這些訊息通知視窗它被啟用了。非隊列訊息也可以由當應用程式調用系統函數產生。例如,當程式調用SetWindowPos系統發送WM_WINDOWPOSCHANGED訊息。一些函數也發送非隊列訊息,例如下面我們要談到的函數。
訊息的發送
瞭解了上面的這些基礎理論之後,我們就可以進行一下簡單的訊息發送與接收。
把一個訊息發送到視窗有3種方式:發送、寄送和廣播。
發送訊息的函數有SendMessage、SendMessageCallback、SendNotifyMessage、SendMessageTimeout;寄送訊息的函數主要有PostMessage、PostThreadMessage、PostQuitMessage;廣播訊息的函數我知道的只有BroadcastSystemMessage、BroadcastSystemMessageEx。
SendMessage的原型如下:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam),這個函數主要是向一個或多個視窗發送一條訊息,一直等到訊息被處理之後才會返回。不過需要注意的是,如果接收訊息的視窗是同一個應用程式的一部分,那麼這個視窗的視窗函數就被作為一個子程式馬上被調用;如果接收訊息的視窗是被另外的線程所建立的,那麼視窗系統就切換到相應的線程並且調用相應的視窗函數,這條訊息不會被放進目標應用程式隊列中。函數的傳回值是由接收訊息的視窗的視窗函數返回,返回的值取決於被發送的訊息。
PostMessage的原型如下:BOO......餘下全文>>
怎從訊息佇列中查詢訊息
PeekMessage();