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

时间:2012-11-13 18:04:29

标签: winapi visual-c++

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

PostMessage(hwnd, WM_QUIT, NULL, NULL);

一切正常,消息变为hW并将其关闭。但如果我正在发送

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

消息根本没有。间谍++也表明消息没有达到hW。有什么特定的WM_SETTEXT,这可以防止它吗?提前谢谢。

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

Turns out the API tries to protect me against scope issues; PostMessage() 
always fails with WM_SETTEXT, or any other system-defined message that has
a pointer as a parameter.Which gets me to SendMessage(), which is not good,
because i wanted asynchronous messaging....


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

SendMessage(hwnd, WM_QUIT, NULL, NULL);

对app.Even没有任何作用,只需要像

这样的简单测试应用
 HWND hNote;
 if (!(hNote=FindWindow(L"Notepad",NULL)))
        exit(1);
 SendMessage(hNote, WM_QUIT, NULL, NULL);

PostMessage(hNote, WM_QUIT, NULL, NULL);

有效。所有看起来对我来说都不符合逻辑的......是否有一些适用于任何类型信息的通用功能?

3 个答案:

答案 0 :(得分:8)

不同的消息有不同的要求。有些需要发布到队列中。有些需要同步交付。因此,该系统旨在需要两种交付机制。

WM_SETTEXT的情况下,它总是需要同步传递。那是因为窗口管理器需要能够管理文本数据的生命周期。 Raymond Chen谈到了这个问题:Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?

当窗口在另一个进程中时,调用SendMessage会有危险。如果其他进程挂起,那么您的进程也不会挂起。因为SendMessage是同步的。

解决方法是致电SendMessageTimeout。这会将您的字符串数据封送到其他进程中。并且您可以设置超时以确保在其他进程挂起的情况下,您的进程可以避免这种命运。

答案 1 :(得分:1)

从您的上一个问题开始:不,没有通用消息功能可以执行您想要的操作。

让我们分析你的案例:

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

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

  3. (1)标准消息循环:

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

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

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

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

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

    4. 套接字。

答案 2 :(得分:0)

你要做的是传达两个独立的过程,常规消息不起作用,但有一个可以做到这一点:WM_COPYDATA消息。可以找到相关问题here