【问题标题】:Sending messages to TApplication向 TApplication 发送消息
【发布时间】:2014-10-10 23:24:28
【问题描述】:

我有一个可以向另一个应用程序发送消息的应用程序。在 Win8 之前的系统下,这工作正常。你给它类或标题,它使用 enumwindows 并找到目标窗口。使用 Win8,您只能枚举顶级窗口,即 TApplication 类。发送方对此感到满意,但接收方不满意。

为了捕捉我在目标表单中使用此代码的消息...

function Tmain.AppMsgHookFunc(var wmsg : TMessage) : Boolean;
begin
  Result := False; 
  if wmsg.Msg = WM_COPYDATA then begin
    // Post the caught message back to this form.
    postmessage (handle,wmsg.Msg,wmsg.WParam,wmsg.LParam);
  end;
end;

...然后使用 application.hookmainwindow 等激活它。

这永远不会触发。我看到如果我使用 sendmessage 向自己发送消息,那么它确实会触发,但是如果我使用 postmessage 不起作用,即使在 XP 上也是如此。有什么建议吗?

【问题讨论】:

    标签: delphi winapi


    【解决方案1】:

    WM_COPYDATA 是已发送的消息。系统跨进程编组数据。为此,系统必须知道消息已被处理,以便能够整理用于进行跨进程编组的资源。而系统知道消息已被处理的方式是强制你同步发送。这意味着您必须使用SendMessage 而不是PostMessage

    documentation 也包含此信息,尽管您确实需要知道如何解释它。

    一个应用程序发送 WM_COPYDATA 消息以将数据传递给另一个应用程序。

    请注意“发送”一词的使用。那是消息同步的代码。

    Raymond Chen 在这里讨论这个问题:Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?

    从消息的角度来看,重要的区别是 WM_COPYDATA 是发送消息,窗口管理器知道什么时候 消息处理完成:当窗口过程返回时。在 那时,它可以释放用于编组的临时缓冲区 从发件人到收件人的消息。如果消息被发布, 窗口管理器永远不会确定。

    假设消息被放置在一个 MSG 结构中,作为一个 调用 GetMessage。现在窗口管理器知道接收 线程有可能对消息和 缓冲区必须有效。但是它怎么知道缓冲区什么时候可以 被释放? “好吧,你可以等到获得完全相同的参数 将 MSG 结构传递给 DispatchMessage 函数。”但是什么 如果消息循环丢弃消息?或者如果它决定 发送两次?或者如果它决定把它偷运到另一个里面怎么办 留言?

    发布的消息不保证送达,也不提供任何 有关何时明确处理消息的信息,或 即使它已经被处理过。如果窗口管理器让你 发布一条 WM_COPYDATA 消息,它必须使用它的精神力量 知道什么时候可以释放内存。

    【讨论】:

    • 这非常有用,非常感谢您的详细回答!
    猜你喜欢
    • 2019-09-16
    • 2015-07-13
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2019-11-13
    • 2017-12-27
    相关资源
    最近更新 更多