Windows API SendMessage 和 PostMessage 內部實現

windows消息之PostMessage和SendMessage的內部實現

 

 

原文:http://blog.csdn.net/sunyikuyu/article/details/8811400

PostMessage和SendMessage是常用的發送消息函數。那兩者有什麼區別呢?

大家都知道PostMessage是向一個窗口Post一個消息,並且不再關注該消息是否被處理。

SendMessage是向窗口發送完消息後,會一直等着該窗口把消息處理完成。

那下面的問題你能回答麼

1. PostMessage向自身線程窗口發消息與向非自身線程窗口發消息實現方法一樣麼?

2. SendMessage向自身線程窗口發消息與向非自身線程窗口發消息實現方法一樣麼?

3. SendMessage的窗口非自身進程,需要做額外的操作麼?

4. SendMessage怎麼實現消息的同步?

如果你知道上面的答案,那請關閉該頁面。

以下內容參考了ReactOS 0.3.14源碼,並從中整理而來。

PostMessage函數大致分爲以下步驟:

1.    如果Wnd爲Null,則是一個當前線程消息(與窗口無關),調用UserPostThreadMessage函數處理

1.1. Copy 消息結構到內核(消息結構的Wnd成員爲Null)

1.2.  把該消息結構掛接到Wnd對應的線程消息隊列中的Post消息鏈表中

1.3.   置線程消息隊列的消息事件爲有信號狀態,通知它有新消息來了

2.  如果Wnd爲0xFFFF,則該消息是一個廣播,則向該桌面所有頂層窗口發送該消息。使用UserPostMessage函數 

3. Wnd不爲Null也不爲0xFFFF,則該窗口爲一個有效窗口,這時候會檢查Msg是否等於WM_QUIT

3.1. 如果Msg等於WM_QUIT

3.1.1. 置消息隊列的QuitPosted字段爲True

3.1.2. 置退出碼到QuitExitCode字段

3.1.3. 置線程消息隊列的消息事件爲有信號狀態,通知它有新消息來了 

3.2. 如果Msg不等於WM_QUIT

3.2.1. Copy 消息結構到內核(這樣可以進程間共享)

3.2.2.  把該消息結構掛接到Wnd對應的線程消息隊列中的Post消息鏈表中

3.2.3.   置線程消息隊列的消息事件爲有信號狀態,通知它有新消息來了

SendMessage函數大致分爲以下步驟:

1. 複製一份消息結構到內核中,以後就使用內核這份消息結構

2. 如果Wnd屬於自身線程,則直接調用窗口自身的消息處理函數處理該消息

3.    如果WND不屬於自身線程窗口

3.1. 構建一個消息結構,並且初始化一個Event事件,如果該消息被處理,該事件就會變成有信號狀態 

3.2.  把該消息結構掛接到Wnd對應的線程消息隊列中的Send消息鏈表中

3.3.   置線程消息隊列的消息事件爲有信號狀態,通知它有新消息來了

3.4.  調用KeWaitForSingleObject無限等待Event事件。直到變成有信號狀態

3.5.    如果消息被處理,則返回

有上面的說明可知,PostMessage比SendMessage簡潔的多。

另外SendMessage有好幾個變種,如SendMessageCallback、SendMessageTimeout等。

SendMessageCallback是吧消息放入Send消息鏈表中後,不會等待消息被執行,而是直接返回。當該消息被執行時,CallBack函數就會被調用

SendMessageTimeout是KeWaitForSingleObject有限等待。如果超時未處理則返回,並把該消息從Send消息列表中摘除。

最後,回答一下上面提到的問題:

1. PostMessage向自身線程窗口發消息與向非自身線程窗口發消息實現方法一樣麼?

  一樣 

2. SendMessage向自身線程窗口發消息與向非自身線程窗口發消息實現方法一樣麼?

不一樣 

3. SendMessage的窗口非自身進程,需要做額外的操作麼?

消息與進程無關 

4. SendMessage怎麼實現消息的同步?

通過KeWaitForSingleObject等待Event事件。該消息被處理時Event就會被置成有信號狀態 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章