消息的投遞(Post)過程相似於普通訊件的投遞過程。普通訊件經過郵遞員到達收信方的信箱裏,收信方取得該信,閱讀信件內容,並可能回信。在這個過程當中,郵遞員的責任只是將信件送到收信者的信箱,一切任務就完成了。異步
消息的發送(Send)過程理解爲打電話交流的過程。甲找到乙的電話號碼,而後開始撥號。若是運氣好,撥通了乙的電話,那麼兩人就聯繫上了。假設甲方從不主動掛斷電話,那麼只有乙方先掛斷電話,兩人的一次聯繫才宣告結束。函數
PostMessage函數spa
BOOL PostMessage( HWND hWnd, //目標窗口句柄 UINT Msg, //消息 WPARAM wParam, //第一個消息參數 LPARAM lParam //第二個消息參數 );
CWnd::PostMessage提供了對PostMessage的簡單包裝,他首先斷言窗口句柄表示一個窗口,而後以窗口句柄爲第一個參數調用全局的PostMessage:線程
_AFXWIN_INLINE BOOL CWnd::PostMessage(UINT message, WPARAM wParam, LPARAM lParam) { ASSERT(::IsWindow(m_hWnd)); return ::PostMessage(m_hWnd, message, wParam, lParam); }
hWnd有兩個特殊的值:HWND_BROADCAST和NULL。前者表示要將該消息投遞到系統當前全部的非子窗口。後者表示由線程而不是某個窗口的窗口過程來處理該消息。
Msg表示投遞的消息標誌,最後兩個參數則表示特定於該消息的參數。千萬要注意,由於投遞消息相似於異步調用,因此在消息參數中傳遞指針是很是危險。指針
SendMessage函數code
LRESULT SendMessage( HWND hWnd, //接收消息的目標窗口 UINT Msg, //消息標誌 WPARAM wParam, //第一個消息參數 LPARAM lParam //第二個消息參數 );
能夠將hWnd的參數設置爲HWND_BROADCAST,表示系統全部的非子窗體廣播此消息。blog
爲了不調用線程陷入永久的等待狀態,能夠用SendMessageTimeout代替SendMessage:回調函數
LRESULT SendMessageTimeout( HWND hWnd, //窗口句柄 UINT Msg, //消息標記 WPARAM wParam, //第一個消息參數 LPARAM lParam, //第二個消息參數 UINT fuFlags, //消息發送選項 UINT uTimeout, //超時,以毫秒爲單位 PDWORD_PTR lpdwResult, //返回值,依賴於特定的消息 );
關鍵是fuFlag參數,它決定了該如何發送該消息,fuFlag參數的值及含義以下表:table
值 | 說 明 |
SMTO_ABORTIFHUNG | 若是目標線程處於掛起狀態,調用線程將不等待超時而當即返回 |
SMTO_BLOCK | 阻止調用線程在目標線程處理完消息以前處理其餘請求 |
SMTO_NORMAL | 在等待目標線程處理消息時,容許調用線程處理其餘請求 |
SMTO_NOTIMEOUTIFNOTHUNG | 對於XP/WIN2000有意義:若是目標線程未掛起,調用線程即便發生超時也會等待目標線程處理完該消息 |
若是調用成功,SendMessageTimeout會返回非0值;若是調用失敗或發生超時,則返回0。爲了防止調用線程被無限等待,能夠將fuFlag參數設爲SMTO_BLOCK,並設置必定的超時時間。class
說明:若是是廣播消息,假定有兩個目標窗口將處理該消息,那麼目標線程將總共有2*uTimeout毫秒的等待期。
CWnd::SendMessage對SendMessage進行了簡單的包裝,它驗證窗口句柄的有效性,而後調用SendMessage API函數:
_AFXWIN_INLINE LRESULT CWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam) { ASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, message, wParam, lParam); }
提示:CWnd沒有提供對SendMessageTimeout的包裝。
同屬於SendMessage系列的API還有SendNotifyMessage和SendMessageCallback,其行爲特性介於PostMessage和SendMessage之間。
SendNotifyMessage函數:
BOOL SendNotifyMessage( HWND hWnd; //窗口句柄 UINT Msg; //消息標誌 WPARAM wParam, //第一個消息參數 LPARAM lParam //第二個消息參數 );
若是hWnd窗口由調用線程建立,那麼其行爲特性跟SendMessage相同,這時將等待消息處理完畢後才返回。若是hWnd由另外一線程建立,其行爲特性則與PostMessage相同,它沒必要等待目標線程處理完該消息而直接返回。
SendMessageCallback函數:
SendMessageCallback的行爲特性相似於PostMessage,也是在發出消息後,不等待目標窗口處理該消息就馬上返回,但它容許消息處理完畢後,讓系統執行指定的函數。
BOOL SendMessageCallback( HWND hWnd, //窗口句柄 UINT Msg, //消息標誌 WPARAM wParam, //第一個消息參數 LPARAM lParam, //第二個消息參數 SENDASYNCPROC lpCallBack, //回調函數 ULONG_PTR dwData //應用範圍內的數據 );
SENDASYNCPROC是回調函數的類型,它具備以下形式的簽名:
VOID CALLBACK SendAsyncProc( HWND hwnd, //目標窗口的句柄 UINT uMsg, //消息標記 ULONG_PTR dwData, //應用範圍的數據 LRESULT lResult //消息處理結束,依賴於特定的消息 );
傳入回調函數的dwData正是在SendMessageCallback中的dwData參數指定的。