发送和接收 Windows 消息

发布于 2024-09-07 04:16:39 字数 505 浏览 5 评论 0原文

Windows 消息似乎是通知 Windows 操作系统上的应用程序的好方法。它实际上工作得很好,但我想到了几个问题:

如何向 SendMessage 例程的 lparam 指定结构化数据(就像许多消息代码那样)?我的意思是...参数当然是一个指针,但是进程如何访问它呢?也许它是由发送/接收消息的进程加载的 DLL 分配的?

是否可以共享消息结构参数(发送者和接收者之间)?它们在发送操作和查看操作之间编组?如果是这样的话,是否可以通过修改结构化参数来从调用者返回数据?这对于 SendMessage 很有用,因为它是同步执行的,而不是 PostMessage 例程。

其他疑惑...

PostMessageSendNotifyMessage有什么区别?

应用程序向自身调用SendMessage是否可能导致死锁在处理消息泵时?

Windows messages seems a good way to notify an application on Windows OSes. It actually works well, but few question comes up to my mind:

How to specify structured data to the lparam of the SendMessage routines (like many message codes does)? I mean... of course the parameter is a pointer, but how the process access to it? Maybe is it allocated by a DLL loaded by the processes sending/receiving the message?

Is it possible to share message structured parameters (between sender and receiver)? They are marshalled between the send operation and the peeking operation? If this is the case, it is possible to return data from the caller by modifying the structured parameter? This could be usefull with SendMessage, since it is executed synchronously, instead the PostMessage routine.

Other doubts...

What the differences from PostMessage and SendNotifyMessage?

Is it possible to cause a deadlock in the case an application calls SendMessage to itself while processing the message pump?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

那小子欠揍 2024-09-14 04:16:39

如果消息是标准窗口消息之一 - 通常消息 ID 介于 0 和 WM_USER 之间,则系统窗口消息调度逻辑包含将结构编组到消息调度到的任何进程的代码。

WM_USER 以上的消息没有得到这样的处理 - 这包括 Windows 95 引入的所有常见控制消息 - 您无法结束任何 LVM_* (列表视图消息)或其他新的控制消息到不同进程中的控件并获得结果后退。

WM_COPYDATA 是专门作为用户代码在进程之间编组任意数据的通用机制引入的 - 在 WM_COPYDATA 之外(或重用其他 Windows 标准消息),没有办法让 Windows 使用消息队列机制自动将结构化数据编组到另一个进程中。

如果是您自己的代码执行消息的发送和接收,您可以使用 dll 来定义共享内存部分,而不是发送指针(该 dll 在每个进程中的基础可能不同)发送偏移量到共享内存块。

如果您想与不封送数据的外部应用程序交换结构化数据(例如从列表或树视图中提取数据),那么您需要执行 dll 注入,以便可以从“进程内”发送和处理消息。


SendNofityMessage 与 PostMessage 不同,因为 PostMessage 总是将消息放入消息队列中,而 SendNotifyMessage 的作用类似于同一进程中窗口的 SendMessage。然后,即使目标窗口位于另一个进程中,消息也会直接分派到窗口过程,而不是通过 GetMessage 或 PeekMessage 放入发布消息队列中进行检索。


最后,可能会导致死锁 - 然而,在“阻塞”sendmessage 等待另一个线程回复时,SendMessage 将分派从其他线程发送(未发布)的消息 - 以防止死锁。这可以缓解大多数潜在的死锁,但仍然可能通过调用其他阻塞 api 或进入模态消息处理循环来创建死锁。

If the message is one of the standard window's messages - usually with a message id between 0 and WM_USER, then the systems window message dispatching logic contains code to marshal the struct to the any processes the message is dispatched to.

Messages above WM_USER get no such treatment - and this includes all the common control messages introduced with Windows 95 - you cannot end any of the LVM_* (list view messages) or other new control messages to a control in a different process and get a result back.

WM_COPYDATA was specifically introduced as a general purpose mechanism for user code to marshal arbitrary data between processes - outside of WM_COPYDATA (or reusing other windows standard messages) there is no way to get windows to automatically marshal structured data using the message queue mechanism into another process.

If it is your own code doing the sending AND receiving of messages, you could use a dll to define a shared memory section, instead of sending pointers (the dll might be based differently in each process) sends offsets to the shared memory block.

If you want to exchange structured data with external applications that do not marshal their data (for example to extract data from a list or tree view) then you need to perform dll injection so you can send and process the message from "in-process".


SendNofityMessage is different to PostMessage because PostMessage always puts the message in the message queue, whereas SendNotifyMessage acts like SendMessage for windows in the same process. Then, even if the target window is in another process, the message is dispatched DIRECTLY to the window proc not placed in the posted message queue for retreivel via GetMessage or PeekMessage.


Lastly it is possible to cause a deadlock - however while in a "blocking" sendmessage waiting for another thread to reply, SendMessage will dispatch messages sent (not posted) from other threads - to prevent deadlocks. This mitigates most potential deadlocks, but its still possible to create deadlocks by calling other blocking apis, or going into modal message processing loops.

ゞ记忆︶ㄣ 2024-09-14 04:16:39

您的担忧主要适用于在进程之间发送消息的情况 - 在进程内,您可以只发送一个指针,发送者只需确保数据保持有效,直到接收者完成使用它。

某些进程间消息要求您使用HGLOBAL(例如,剪贴板消息)。其他则需要明确的块大小(例如,使用WM_COPYDATA)。还有一些以预先指定的结构(例如,以零结尾的字符串)发送数据以支持编组。

一般来说,您无法通过修改收到的块来返回值。要返回值,您需要(例如)发送回复消息。

SendMessage 有一些(相当复杂的)逻辑来防止死锁,但您仍然需要小心。

Your concerns apply primarily in the case of messages sent between processes -- within a process, you can just send a pointer, and the sender just has to ensure the data remains valid until the receiver is finished using it.

Some interprocess messages require you to work with an HGLOBAL (e.g., the clipboard messages). Others require an explicit block size (e.g., with WM_COPYDATA). Still others send data in a pre-specified structure (e.g., a zero-terminated string) to support marshalling.

Generally speaking you can't return a value by modifying the block you received. To return a value, you need to (for example) send a reply message.

SendMessage has some (fairly complex) logic to prevent deadlocks, but you still need to be careful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文