2010-06-29 205 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有一些(相当复杂的)逻辑来防止死锁,但你仍然需要小心。