PostMessage(hwnd, WM_SETTEXT,..) 不起作用,而 PostMessage(hwnd, WM_QUIT,..) 起作用

问题描述 投票:0回答:3

我有 2 个应用程序,一个是隐藏窗口(“hW”),另一个是控制台应用程序(“CA”),来自 我想向硬件发送命令。 在控制台应用程序中,我得到了硬件句柄,这是一个问题: 如果我跑步:

PostMessage(hwnd, WM_QUIT, NULL, NULL);

一切正常,消息到达硬件并将其关闭。但是如果我正在发送

PostMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)"texttext");

消息根本没有到达硬件。 Spy++ 还显示消息未到达硬件。 WM_SETTEXT 有什么特定的东西可以阻止它吗?预先感谢。

好的。在这里找到答案http://cboard.cprogramming.com/windows-programming/72589-wm_settext-postmessage.html

事实证明 API 试图保护我免受范围问题的影响;发布消息()
总是因 WM_SETTEXT 或任何其他系统定义的消息而失败
一个指针作为参数。这让我进入 SendMessage(),这不好,
因为我想要异步消息传递......


P.P.S.
另外,看起来像

SendMessage(hwnd, WM_QUIT, NULL, NULL);

不会对目标应用程序执行任何操作。即使在像

这样的简单测试应用程序中也是如此
 HWND hNote;
 if (!(hNote=FindWindow(L"Notepad",NULL)))
        exit(1);
 SendMessage(hNote, WM_QUIT, NULL, NULL);

同时

PostMessage(hNote, WM_QUIT, NULL, NULL);

有效。
所有这些对我来说看起来都不合逻辑...是否有一些通用函数可以正确处理任何类型的消息?

winapi visual-c++
3个回答
8
投票

不同的消息有不同的要求。有些需要发布到队列中。还有一些需要同步交付。因此,系统被设计为需要两种交付机制。

对于

WM_SETTEXT
的情况,总是需要同步传递。这是因为窗口管理器需要能够管理文本数据的生命周期。 Raymond Chen谈到了这个问题:为什么我不能PostMessage WM_COPYDATA消息,但我可以SendMessageTimeout它并有一个微小的超时?

当窗口处于另一个进程中时,调用

SendMessage
存在危险。如果其他进程挂起,您的进程也不会挂起。因为
SendMessage
是同步的。

解决方案是拨打

SendMessageTimeout
。这会将您的字符串数据编组到其他进程中。您可以设置超时,以确保在其他进程被挂起的情况下,您的进程可以避免这种命运。


1
投票

从你的最后一个问题开始:不,没有一个通用的消息功能可以满足你的要求。

让我们分析一下您的案例:

  1. WM_SETTEXT
    :该消息需要一个指针,因此您无法在进程之间安全地发布它,因为它们将具有单独的内存地址,并且来自一个进程的指针对另一个进程毫无意义。您可以使用
    SendMessage()
    ,因为Windows知道该消息,在幕后复制数据并进行额外的黑客攻击。但有了
    PostMessage()
    就没有(不可能)这样的魔法了。

  2. WM_QUIT
    :这是一条特殊消息,会导致消息循环中断。简而言之,它所做的只是使
    GetMessage
    返回
    FALSE
    ,以便标准消息循环(1)完成。但是,啊!只有当你
    PostMessage()
    时,这才会起作用。当您
    SendMessage()
    一条消息时,它会直接发送到相关的窗口函数,甚至不会停留在消息队列中。 Windows 对
    WM_QUIT
    没有任何作用,因为它们根本就没有期待它。实际上,即使发布了该消息,该消息也不会到达窗口,因为通常的循环不会为其调用
    DispatchMessage()
    。这就是为什么它通常被发布到线程,没有窗口,因此存在一个函数可以完成所有这一切:
    PostQuitMessage()

(1) 标准消息循环:

while (GetMessage(&msg, 0, 0, 0))
    DispatchMessage(&msg);

作为脚注,您可以使用多种技巧在进程之间移动数据:

  1. 使用

    WM_COPYDATA
    。 AFAIK 它不能与
    PostMessage()
    一起使用,但也许您可以在目标进程中创建两个线程,以便第一个线程接收
    WM_COPYDATA
    并快速返回,然后将其发布到第二个线程排队。

  2. 使用共享内存(搜索

    CreateFileMapping()
    )和
    PostMessage()
    到该内存的偏移量。您可能应该使用一些
    WM_APP + x
    用户定义的消息而不是系统消息。但是,请注意同步问题,您将需要互斥锁或其他东西。

  3. 命名管道! (我的最爱)

  4. 插座。


0
投票

您想要做的是传达两个独立的进程,常规消息不起作用,但有一个可以解决这个问题:

WM_COPYDATA
消息。相关问题可以在这里找到

© www.soinside.com 2019 - 2024. All rights reserved.