2010-06-29 177 views
2

Windows消息似乎是在Windows操作系統上通知應用程序的好方法。它實際上運作良好,但少數問題來了,以我的腦海:發送和接收Windows消息

如何指定結構化數據到LPARAM的SendMessage函數例程(如許多消息代碼呢)?我的意思是......當然這個參數是一個指針,但是過程如何訪問它呢?也許是由發送/接收消息的進程加載的DLL分配的?

是否有可能共享消息結構參數(發送者和接收者之間)?他們被編組在之間發送操作和查看操作?如果是這種情況,可以通過修改結構化參數來從調用者返回數據?這可能對SendMessage有用,因爲它是同步執行的,而不是PostMessage例程。

其他疑惑...

從什麼PostMessage的SendNotifyMessage的區別是什麼?

在應用程序在處理消息泵時調用SendMessage到自己的情況下,是否可能導致死鎖?

回答

4

如果消息是標準窗口的消息之一 - 通常消息ID介於0和WM_USER之間,那麼系統窗口消息調度邏輯包含代碼以將消息發送到的任何進程編組爲結構的代碼。

WM_USER上面的消息沒有得到這樣的處理 - 這包括Windows 95引入的所有常見控制消息 - 您不能將任何LVM_ *(列表視圖消息)或其他新控制消息結束到不同進程中的控件並返回結果。

WM_COPYDATA是作爲用戶代碼的通用機制專門引入的,以封送進程之間的任意數據 - 在WM_COPYDATA之外(或重用其他Windows標準消息),無法讓窗口使用消息隊列自動封送結構化數據機制進入另一個過程。

如果它是你自己的代碼做消息的發送和接收,你可以使用dll來定義一個共享內存部分,而不是發送指針(dll在每個進程中可能會有不同的基礎)將偏移量發送到共享內存塊。

如果您想要與不編組數據的外部應用程序交換結構化數據(例如從列表或樹形視圖中提取數據),則需要執行dll注入,以便您可以發送和處理來自「在進程中」。


SendNofityMessage是PostMessage的不同,因爲PostMessage的總是把在消息隊列中的消息,而SendNotifyMessage就像的SendMessage用於在相同的工藝窗口。然後,即使目標窗口處於另一個進程中,也會通過GetMessage或PeekMessage將消息直接分發給未放入retreivel的已發佈消息隊列中的窗口proc。


最後有可能導致死鎖 - 但同時在「堵」的SendMessage等待另一個線程來回復,SendMessage函數將派遣派(未公佈)從其他線程的消息 - 防止死鎖。這可以緩解大多數潛在的死鎖,但它仍然可能通過調用其他阻塞apis或進入模態消息處理循環來創建死鎖。

+0

如何在共享DLL的堆上分配內存? – Luca 2010-06-29 19:59:12

+0

怎麼樣?我提到過它。我還提到它不安全,因爲dll和共享內存段可能會在每個進程的不同基地址中加載 - 因此接收代碼必須知道這一點 - 這使得它不像通常的第3種方法那樣安全派對代碼。 – 2010-06-29 20:09:30

+0

@Luca:一般來說,DLL使用其宿主進程的堆。因此,共享DLL並不意味着共享堆。 – MSalters 2010-07-01 14:34:24

0

您的問題主要適用於進程之間發送的消息 - 在進程內,您只需發送一個指針,並且發送者只需確保數據保持有效,直到接收者完成使用。

某些進程間消息要求您使用HGLOBAL(例如剪貼板消息)。其他需要明確的塊大小(例如,與WM_COPYDATA)。還有一些用預先指定的結構發送數據(例如零終止字符串)以支持編組。

一般來說,您不能通過修改您收到的塊來返回值。要返回值,您需要(例如)發送回覆消息。

SendMessage有一些(相當複雜的)邏輯來防止死鎖,但你仍然需要小心。