1. 程式人生 > >C++中SendMessage與PostMessage的區別

C++中SendMessage與PostMessage的區別

Send有傳送的意思,而Post具有投寄的意思。 聯想一下現實生活中我們寫信(很久很久以前。。。。)來記就很簡單了:

  • Send: 相當於郵寄員,他會將快件親手交給收件人,並且需要收件人簽字,他才閃人。而在訊息機制中,就是說,系統(郵寄員)會將收到的訊息(郵局分發)直接傳送到某個視窗的視窗過程(收件人),並且需要該視窗作出處理(收件人簽字)才返回。 這東東就是SendMessage。
  • Post: 相當於郵局、郵筒等等,我們寫好信好,會將信交給郵局,或投寄到郵筒裡,而什麼時候傳送,傳送到哪裡都由郵局來處理,我們投寄信件的時候,是不會等候這封信件到達收件人手裡,然後才回家的。

在訊息機制中,就是說,系統(我們)將收到的訊息(信件)投寄到應用程式的訊息迴圈(相當於郵筒)中,然後就閃人,具體啥時候處理這條訊息(啥時候傳送郵件),那就得看“辦事效率”了。

一、SendMessage

將指定的訊息傳送到一個視窗或多個視窗。SendMessage為這個指定的訊息呼叫視窗處理程式,直到視窗處理完這個程式後才會返回。和SendMessage函式相比,PostMessage函式傳送一個訊息到執行緒訊息對列中,並立即返回。

函式原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
  • 引數:

hWnd:其視窗程式將接收訊息的視窗的控制代碼。如果此引數為HWND_BROADCAST,則訊息將被髮送到系統中所有頂層視窗,包括無效或不可見的非自身擁有的視窗、被覆蓋的視窗和彈出式視窗,但訊息不被髮送到子視窗。
Msg

:指定被髮送的訊息。
wParam:指定附加的訊息指定資訊。
IParam:指定附加的訊息指定資訊。

  • 返回值:返回值指定訊息處理的結果,依賴於所傳送的訊息。
備註:需要用HWND_BROADCAST通訊的應用程式應當使用函式RegisterWindowMessage來為應用程式間的通訊取得一個唯一的訊息。

如果指定的視窗是由呼叫執行緒建立的,則視窗程式立即作為子程式呼叫。如果指定的視窗是由不同執行緒建立的,則系統切換到該執行緒並呼叫恰當的視窗程式。執行緒間的訊息只有在執行緒執行訊息檢索程式碼時才被處理。傳送執行緒被阻塞直到接收執行緒處理完訊息為止。

二、PostMessage

該函式將一個訊息放入(寄送)到與指定視窗建立的執行緒相聯絡訊息佇列裡,不等待執行緒處理訊息就返回。訊息佇列裡的訊息通過呼叫GetMessage和PeekMessage取得。

函式原型:B00L PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
  • 引數:

hWnd:其視窗程式接收訊息的視窗的控制代碼。可取有特定含義的兩個值:
1.HWND.BROADCAST:訊息被寄送到系統的所有頂層視窗,包括無效或不可見的非自身擁有的視窗、被覆蓋的視窗和彈出式視窗。訊息不被寄送到子視窗。
2.NULL:此函式的操作和呼叫引數dwThread設定為當前執行緒的識別符號PostThreadMessage函式一樣。
Msg:指定被寄送的訊息。
wParam:指定附加的訊息特定的資訊。
IParam:指定附加的訊息特定的資訊。

  • 返回值:如果函式呼叫成功,返回非零值:如果函式呼叫失敗,返回值是零。若想獲得更多的錯誤資訊,請呼叫GetLastError函式。

三、分析

  • 1, PostMessage只把訊息放入佇列,不管其他程式是否處理都返回,然後繼續執行,這是個非同步訊息投放函式。而SendMessage必須等待其他程式處理訊息完了之後才返回,繼續執行,這是個同步訊息投放函式
  • 2, 如果在同一個執行緒內,PostMessage傳送訊息時,訊息要先放入執行緒的訊息佇列,然後通過訊息迴圈Dispatch到目標視窗。SendMessage傳送訊息時,系統直接呼叫目標視窗的訊息處理程式,並將結果返回,SendMessage在同一執行緒中傳送訊息並不入執行緒訊息佇列。
  • 3,PostMessage的返回值表示PostMessage函式執行是否正確;而SendMessage的返回值表示其他程式處理訊息後的返回值。這點大家應該都明白。
  • 4,如果在不同執行緒內。最好用PostThreadMessage代替PostMessage,他工作的很好,SendMessage傳送訊息到目標視窗所屬的執行緒的訊息佇列,然後傳送訊息的執行緒等待(事實上,他應該還在做一些監測工作,比如監視QS_SENDMESSAGE標誌),直到目標視窗處理完並且結果返回,傳送訊息的執行緒才繼續執行。

四、總結

區別很明顯,SendMessage的訊息是不進佇列的,而PostMessage的需要排隊。值得說明的是:雖然一個要進隊,一個不進隊,但是最終處理訊息的地方都一樣:都是系統呼叫視窗過程進行處理(收件人作出反應)。