Windows API SendMessage 和 PostMessage 內部實現

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

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

你們都知道PostMessage是向一個窗口Post一個消息,而且再也不關注該消息是否被處理。函數

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

那下面的問題你能回答麼.net

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

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

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

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

若是你知道上面的答案,那請關閉該頁面。事件

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

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就會被置成有信號狀態 

相關文章
相關標籤/搜索