1. 視窗過程每個視窗會有一個稱為視窗過程的回呼函數(WndProc),它帶有四個參數,分別為:視窗控制代碼(Window Handle),訊息ID(Message ID),和兩個訊息參數(wParam, lParam), 當視窗收到訊息時系統就會調用此視窗過程來處理訊息。(所以叫回呼函數)
2訊息類型
1)系統定義訊息(System-Defined Messages)
在SDK中事先定義好的訊息,非使用者定義的,其範圍在[0x0000, 0x03ff]之間, 可以分為以下三類:
1>視窗訊息(Windows Message)
與視窗的內部運作有關,如建立視窗,繪製視窗,銷毀視窗等。可以是一般的視窗,也可以是Dialog,控制項等。
如:WM_CREATE, WM_PAINT, WM_MOUSEMOVE, WM_CTLCOLOR, WM_HSCROLL...
2>命令訊息(Command Message)
與處理使用者請求有關, 如單擊功能表項目或工具列或控制項時, 就會產生命令訊息。
WM_COMMAND, LOWORD(wParam)表示功能表項目,工具列按鈕或控制項的ID。如果是控制項, HIWORD(wParam)表示控制項訊息類型
3>控制項通知(Notify Message)
控制項通知訊息, 這是最靈活的訊息格式, 其Message, wParam, lParam分別為:WM_NOTIFY, 控制項ID,指向NMHDR的指標。NMHDR包含控制項通知的內容, 可以任意擴充。
2)程式定義訊息(Application-Defined Messages)
使用者自訂的訊息, 對於其範圍有如下規定:WM_USER: 0x0400-0x7FFF (ex. WM_USER+10) WM_APP(winver>4.0): 0x8000-0xBFFF (ex.WM_APP+4)
RegisterWindowMessage: 0xC000-0xFFFF
3訊息佇列(Message Queues)
Windows中有兩種類型的訊息佇列
1)系統訊息佇列(System Message Queue)
這是一個系統唯一的Queue,裝置驅動(mouse, keyboard)會把操作輸入轉化成訊息存在系統隊列中,然後系統會把此訊息放到目標視窗所在的線程的訊息佇列(thread-specific message queue)中等待處理
2)線程訊息佇列(Thread-specific Message Queue)
每一個GUI線程都會維護這樣一個線程訊息佇列。(這個隊列只有線上程調用GDI函數時才會建立,預設不建立)。然後線程訊息佇列中的訊息會被送到相應的視窗過程(WndProc)處理.注意: 線程訊息佇列中WM_PAINT,WM_TIMER只有在Queue中沒有其他訊息的時候才會被處理,WM_PAINT訊息還會被合并以提高效率。其他所有訊息以先進先出(FIFO)的方式被處理。
4隊列訊息(Queued Messages)和非隊列訊息(Non-Queued Messages)
1)隊列訊息(Queued Messages)
訊息會先儲存在訊息佇列中,訊息迴圈會從此隊列中取訊息並分發到各視窗處理如滑鼠,鍵盤訊息。
2)非隊列訊息(NonQueued Messages)
訊息會繞過系統訊息佇列和線程訊息佇列直接發送到視窗過程被處理
如: WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_WINDOWPOSCHANGED注意: postMessage發送的訊息是隊列訊息,它會把訊息Post到訊息佇列中; SendMessage發送的訊息是非隊列訊息, 被直接送到視窗過程處理
5 PostMessage(PostThreadMessage), SendMessage PostMessage:把訊息放到指定視窗所在的線程訊息佇列中後立即返回。 PostThreadMessage:把訊息放
到指定線程的訊息佇列中後立即返回。
SendMessage:直接把訊息送到視窗過程處理, 處理完了才返回。
6 GetMessage, PeekMessage
PeekMessage會立即返回可以保留訊息
GetMessage在有訊息時返回會刪除訊息
7 TranslateMessage, TranslateAccelerator TranslateMessage: 把一個virtual-key訊息轉化成字元訊息(character message),並放到當前線程的訊息佇列中,訊息迴圈下一次取出處理。
TranslateAccelerator: 將快速鍵對應到相應的功能表命令。它會把WM_KEYDOWN 或 WM_SYSKEYDOWN轉化成快速鍵表中相應的WM_COMMAND 或WM_SYSCOMMAND訊息, 然後把轉化後的 WM_COMMAND或WM_SYSCOMMAND直接發送到視窗過程處理, 處理完後才會返回。
8(訊息死結( Message Deadlocks)
假設有線程A和B, 現在有以下下步驟1) 線程A SendMessage給線程B, A等待訊息線上程B中處理後返回2) 線程B收到了線程A發來的訊息,並進行處理, 在處理過程中,B也向線程A SendMessgae,然後等待從A返回。
因為此時, 線程A正等待從線程B返回, 無法處理B發來的訊息, 從而導致了線程A,B相互等待, 形成死結。多個線程也可以形成環形死結。
可以使用 SendNotifyMessage或SendMessageTimeout來避免出現死結。
9 BroadcastSystemMessage
我們一般所接觸到的訊息都是發送給視窗的, 其實, 訊息的接收者可以是多種多樣的,它可以是應用程式(applications), 可安裝驅動(installable drivers), 網路裝置(network drivers), 系統級裝置驅動(system-level device drivers)等,BroadcastSystemMessage這個API可以對以上系統組件發送訊息。