天天看點

SendMessage and PostMessage的差別

來自于L:http://www.cnblogs.com/yydy1983/archive/2010/03/19/1689932.html

Win32 API消息函數:SendMessage

函數功能:該函數将指定的消息發送到一個或多個視窗。此函數為指定的視窗調用視窗程式,直到視窗程 序處理完消息再傳回。而函數PostMessage不同,将一個消息寄送到一個線程的消息隊列後立即傳回。

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

      參數:

      hWnd:其視窗程式将接收消息的視窗的句柄。如果此參數為HWND_BROADCAST,則消息将被發送到系統中所有頂層視窗,包括無效或不可見的非自 身擁有的視窗、被覆寫的視窗和彈出式視窗,但消息不被發送到子視窗。

      Msg:指定被發送的消息。

      wParam:指定附加的消息指定資訊。

      IParam:指定附加的消息指定資訊。

      傳回值:傳回值指定消息處理的結果,依賴于所發送的消息。

      備注:需要用HWND_BROADCAST通信的應用程式應當使用函數RegisterWindowMessage來為應用程式間的通信取得一個唯一的消 息。

      如果指定的視窗是由調用線程建立的,則視窗程式立即作為子程式調用。如果指定的視窗是由不同線程建立的,則系統切換到該線程并調用恰當的視窗程式。線程間 的消息隻有線上程執行消息檢索代碼時才被處理。發送線程被阻塞直到接收線程處理完消息為止。

      Windows CE:Windows CE不支援Windows桌面平台支援的所有消息。使用SendMesssge之前,要檢查發送的消息是否被支援。

      速查:Windows NT:3.1及以上版本:Windows:95及以上版本;Windows CE:1.0及以上版本;頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。

Win32 API消息函數:PostMessage

      函數功能:該函數将一個消息放入(寄送)到與指定視窗建立的線程相聯系消息隊列裡,不等待線程處理消息就傳回。消息隊列裡的消息通過調用 GetMessage和PeekMessage取得。

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

      參數

      hWnd:其視窗程式接收消息的視窗的句柄。可取有特定含義的兩個值:

      HWND.BROADCAST:消息被寄送到系統的所有頂層視窗,包括無效或不可見的非自身擁有的視窗、被覆寫的視窗和彈出式視窗。消息不被寄送到子窗 口。

      NULL:此函數的操作和調用參數dwThread設定為目前線程的辨別符PostThreadMessage函數一樣。

      Msg:指定被寄送的消息。

      wParam:指定附加的消息特定的資訊。

      IParam:指定附加的消息特定的資訊。

      傳回值:如果函數調用成功,傳回非零值:如果函數調用失敗,傳回值是零。若想獲得更多的錯誤資訊,請調用GetLastError函數。

      備注:需要以 HWND_BROADCAST方式通信的應用程式應當用函數 RegisterwindwosMessage來獲得應用程式間通信的獨特的消息。

      如果發送一個低于WM_USER範圍的消息給異步消息函數 (PostMessage.SendNotifyMessage,SendMesssgeCallback),消息參數不能包含指針。否則,操作将會失 敗。函數将再接收線程處理消息之前傳回,發送者将在記憶體被使用之前釋放。

      速查:Windows NT: 3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本;頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。

在控制别的應用程式的時候,經常需要等待直到某個功能結束,例如:

打開一個視窗-->等待直到視窗結束

這 個時候就可以用到SendMessage

如果在打開這個視窗後仍然需要對該視窗的界面進行設定,比如Edit的value等等,比如:

打 開一個視窗-->控制視窗的control的屬性

這個時候就需要PostMessage

使用一個鈎子程式截獲消息後,使用 SendMessage把消息發送到主處理程式進行處理,但是在主處理程式還沒有完成任務的時候,被設定鈎子的程式進入了停止的狀态,不可以處理

WM_PAINT,

WM_MOVE,

....... 等的基本資訊,

必須要等SendMessage發送出的消息完成後,才能繼續運作,整個界面一片空白,把鈎子消息設定成PostMessage的 發送消息形式後,問題解決!

我查了MSDN對這兩個API的定義,

PostMessage隻是把消息放入隊列,不管其他程式是否處理都返 回,然後繼續執行;

而SendMessage必須等待其他程式處理消息後才傳回,繼續執行。

PostMessage的傳回值表示 PostMessage函數執行是否正确;

而SendMessage的傳回值表示其他程式處理消息後的傳回值。

使用這兩個發送消息函數 的最重要的是要看你的程式是否要對消息的滞後性關注否,PostMessage會造成消息的滞後性,而SendMessage則不會,但如果 SendMessage消息處理失敗,則會造成程式停止!

===============================================

1. SendMessage函數要等到消息被處理後才傳回

    PostMessage 消息發出後馬上傳回

2. PostMessage發向目标視窗的消息一定會進入消息隊列

    SendMessage向同一線程的視窗發消息,不會進入消息隊列,

    SendMessage向其他線程的視窗發消息,則會進入消息隊列,

3. PostMessage的傳回值表示PostMessage函數執行是否正确,

   SendMessage的傳回值表示其他程式處理消息後的傳回值

1、SendMessage()和PostMessage().這兩個函數幾乎是一樣的,它們的差別是:

SendMessage()直接把一個消息發給視窗過程,等消息被處理後才傳回。Postmessage()隻是把消息發送到消息隊列,完成後即傳回。

2.1、當調用SendMessage時,接收消息的線程的QS_SENDMESSAGE标志被設定,系統調用相應的視窗過程來處理這個消息。 GetMessage和PeekMessage函數在内部進行這種處理。如果在“發送消息隊列”中沒有消息了,QS_SENDMESSAGE标志就被關 閉。“發送消息隊列”中可能有幾個Send過來的消息。例如,幾個線程同時向一個視窗發送消息。

2.2、當調用PostMessage時,函數GetMessage或PeekMessage填充傳遞給它們的Msg結構,函數傳回。再調用 DispatchMessage,讓相應的視窗過程來處理消息。

2.3、當調用SendMessage時,發送線程和接收線程是同一個線程的時候,SendMessag很簡單,隻是調用指定視窗的視窗過程。但當 發送線程和接收線程不是同一個線程時,麻煩就大了。因為發送線程和接收線程運作在不同的位址空間中,是以不能通路接受線程中相應視窗過程的代碼和資料。其 實這時發送線程要挂起,當接收線程處理Send過來的消息時,發送線程被設定為空閑(idle)狀态。在發送的消息處理完成後,視窗過程的傳回值被登記到 發送線程的應答消息隊列中。發送線程被喚醒,取出包含在應答消息隊列中的傳回值。這個傳回值就是調用SendMessage的傳回值,這時,發送線程繼續 運作。

2.4、WM_PAINT和WM_TIMER這兩個消息的優先級非常低,最低的是WM_TIMER。

2.5、WM_COPYDATA隻能Send,不能Post。

來自于:Win32 API消息函數:SendMessage

函數功能:該函數将指定的消息發送到一個或多個視窗。此函數為指定的視窗調用視窗程式,直到視窗程 序處理完消息再傳回。而函數PostMessage不同,将一個消息寄送到一個線程的消息隊列後立即傳回。

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

      參數:

      hWnd:其視窗程式将接收消息的視窗的句柄。如果此參數為HWND_BROADCAST,則消息将被發送到系統中所有頂層視窗,包括無效或不可見的非自 身擁有的視窗、被覆寫的視窗和彈出式視窗,但消息不被發送到子視窗。

      Msg:指定被發送的消息。

      wParam:指定附加的消息指定資訊。

      IParam:指定附加的消息指定資訊。

      傳回值:傳回值指定消息處理的結果,依賴于所發送的消息。

      備注:需要用HWND_BROADCAST通信的應用程式應當使用函數RegisterWindowMessage來為應用程式間的通信取得一個唯一的消 息。

      如果指定的視窗是由調用線程建立的,則視窗程式立即作為子程式調用。如果指定的視窗是由不同線程建立的,則系統切換到該線程并調用恰當的視窗程式。線程間 的消息隻有線上程執行消息檢索代碼時才被處理。發送線程被阻塞直到接收線程處理完消息為止。

      Windows CE:Windows CE不支援Windows桌面平台支援的所有消息。使用SendMesssge之前,要檢查發送的消息是否被支援。

      速查:Windows NT:3.1及以上版本:Windows:95及以上版本;Windows CE:1.0及以上版本;頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。

Win32 API消息函數:PostMessage

      函數功能:該函數将一個消息放入(寄送)到與指定視窗建立的線程相聯系消息隊列裡,不等待線程處理消息就傳回。消息隊列裡的消息通過調用 GetMessage和PeekMessage取得。

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

      參數

      hWnd:其視窗程式接收消息的視窗的句柄。可取有特定含義的兩個值:

      HWND.BROADCAST:消息被寄送到系統的所有頂層視窗,包括無效或不可見的非自身擁有的視窗、被覆寫的視窗和彈出式視窗。消息不被寄送到子窗 口。

      NULL:此函數的操作和調用參數dwThread設定為目前線程的辨別符PostThreadMessage函數一樣。

      Msg:指定被寄送的消息。

      wParam:指定附加的消息特定的資訊。

      IParam:指定附加的消息特定的資訊。

      傳回值:如果函數調用成功,傳回非零值:如果函數調用失敗,傳回值是零。若想獲得更多的錯誤資訊,請調用GetLastError函數。

      備注:需要以 HWND_BROADCAST方式通信的應用程式應當用函數 RegisterwindwosMessage來獲得應用程式間通信的獨特的消息。

      如果發送一個低于WM_USER範圍的消息給異步消息函數 (PostMessage.SendNotifyMessage,SendMesssgeCallback),消息參數不能包含指針。否則,操作将會失 敗。函數将再接收線程處理消息之前傳回,發送者将在記憶體被使用之前釋放。

      速查:Windows NT: 3.1及以上版本;Windows:95及以上版本;Windows CE:1.0及以上版本;頭檔案:winuser.h;輸入庫:user32.lib;Unicode:在Windows NT環境下以Unicode和ANSI方式實作。

在控制别的應用程式的時候,經常需要等待直到某個功能結束,例如:

打開一個視窗-->等待直到視窗結束

這 個時候就可以用到SendMessage

如果在打開這個視窗後仍然需要對該視窗的界面進行設定,比如Edit的value等等,比如:

打 開一個視窗-->控制視窗的control的屬性

這個時候就需要PostMessage

使用一個鈎子程式截獲消息後,使用 SendMessage把消息發送到主處理程式進行處理,但是在主處理程式還沒有完成任務的時候,被設定鈎子的程式進入了停止的狀态,不可以處理

WM_PAINT,

WM_MOVE,

....... 等的基本資訊,

必須要等SendMessage發送出的消息完成後,才能繼續運作,整個界面一片空白,把鈎子消息設定成PostMessage的 發送消息形式後,問題解決!

我查了MSDN對這兩個API的定義,

PostMessage隻是把消息放入隊列,不管其他程式是否處理都返 回,然後繼續執行;

而SendMessage必須等待其他程式處理消息後才傳回,繼續執行。

PostMessage的傳回值表示 PostMessage函數執行是否正确;

而SendMessage的傳回值表示其他程式處理消息後的傳回值。

使用這兩個發送消息函數 的最重要的是要看你的程式是否要對消息的滞後性關注否,PostMessage會造成消息的滞後性,而SendMessage則不會,但如果 SendMessage消息處理失敗,則會造成程式停止!

===============================================

1. SendMessage函數要等到消息被處理後才傳回

    PostMessage 消息發出後馬上傳回

2. PostMessage發向目标視窗的消息一定會進入消息隊列

    SendMessage向同一線程的視窗發消息,不會進入消息隊列,

    SendMessage向其他線程的視窗發消息,則會進入消息隊列,

3. PostMessage的傳回值表示PostMessage函數執行是否正确,

   SendMessage的傳回值表示其他程式處理消息後的傳回值

1、SendMessage()和PostMessage().這兩個函數幾乎是一樣的,它們的差別是:

SendMessage()直接把一個消息發給視窗過程,等消息被處理後才傳回。Postmessage()隻是把消息發送到消息隊列,完成後即傳回。

2.1、當調用SendMessage時,接收消息的線程的QS_SENDMESSAGE标志被設定,系統調用相應的視窗過程來處理這個消息。 GetMessage和PeekMessage函數在内部進行這種處理。如果在“發送消息隊列”中沒有消息了,QS_SENDMESSAGE标志就被關 閉。“發送消息隊列”中可能有幾個Send過來的消息。例如,幾個線程同時向一個視窗發送消息。

2.2、當調用PostMessage時,函數GetMessage或PeekMessage填充傳遞給它們的Msg結構,函數傳回。再調用 DispatchMessage,讓相應的視窗過程來處理消息。

2.3、當調用SendMessage時,發送線程和接收線程是同一個線程的時候,SendMessag很簡單,隻是調用指定視窗的視窗過程。但當 發送線程和接收線程不是同一個線程時,麻煩就大了。因為發送線程和接收線程運作在不同的位址空間中,是以不能通路接受線程中相應視窗過程的代碼和資料。其 實這時發送線程要挂起,當接收線程處理Send過來的消息時,發送線程被設定為空閑(idle)狀态。在發送的消息處理完成後,視窗過程的傳回值被登記到 發送線程的應答消息隊列中。發送線程被喚醒,取出包含在應答消息隊列中的傳回值。這個傳回值就是調用SendMessage的傳回值,這時,發送線程繼續 運作。

2.4、WM_PAINT和WM_TIMER這兩個消息的優先級非常低,最低的是WM_TIMER。

2.5、WM_COPYDATA隻能Send,不能Post。

繼續閱讀