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