【问题标题】:The contradiction on the return values of PostMessageA and WM_MOUSEMOVEPostMessageA和WM_MOUSEMOVE返回值的矛盾
【发布时间】:2021-04-20 07:07:41
【问题描述】:

我想使用 Windows api PostMessageA 发布 WM_MOUSEMOVE 消息。在WM_MOUSEMOVE 上的微软文档中,它说:

如果应用程序处理此消息,它应该返回零。

PostMessageA 上,它说:

如果函数成功,返回值非零。如果函数失败,则返回值为零。要获取扩展错误信息,请调用 GetLastError。 GetLastError 在达到限制时返回 ERROR_NOT_ENOUGH_QUOTA。

它们不是矛盾的吗?在我的程序中,我写了这些代码:

// ...
// mainGameWnd is the handle on the main window
// wParamRawMouse = 0, which indicates no mouse button was pressed
// _mouse_position.x and _mouse_position.y are LONG type
if ((PostMessageA(mainGameWnd, WM_MOUSEMOVE, wParamRawMouse, MAKELPARAM(_mouse_position.x, _mouse_position.y))) == 0);
{
    // error logging
    LogError("post message in Mouse move failed. Error: %ld", GetLastError());
}

在日志文件中,我找到了这一行:

[Error]:  post message in Mouse move failed. Error: 0

返回的“0”到底是什么意思?这是否意味着PostMessageA 失败,我应该检查发送到其中的参数,或者只是消息已成功处理,我不需要执行任何操作?

附录

关于日志错误

// global: FILE* logFile = stdout;
// lastLog is enum
void Log(LogCategory level, LPCSTR format, bool append, va_list args)
{
    lastLog = level;
    if (!(LogFlag & (1 << level)))
        return;
    if (logEventFunc)
    {
        if (!logEventFunc(level, format, append, args))
            return;
    }
    if (!append)
    {
        time_t rawtime;
        char pblgtime[128] = { 0 };
        time(&rawtime);
        switch (level)
        {
        case Log_Error: strftime(pblgtime, 128, "%Y-%m-%d %X [Error]:  ", localtime(&rawtime)); break;
        }
        fprintf(logFile, pblgtime);
    }
    vfprintf(logFile, format, args);
    fflush(logFile);
}

void LogError(LPCSTR format, ...)
{
    va_list args;
    va_start(args, format);
    Log(Log_Error, format, false, args);
    va_end(args);
}

【问题讨论】:

  • PostMessage 返回的值与您的应用程序从其窗口过程返回的值不同。没有矛盾。
  • LogError 扩展为什么?
  • @molbdnilo 感谢您的评论。那么上面示例的结果是否表明 postmessage failed ?而 LogError 只是将格式化的字符串写入文件。
  • 这表示 1) 失败,2) 你的 LogError 宏在调用 GetLastError 之前做了一些事情。 (我没有问LogError 是做什么的,我问的是它扩展为什么;它的定义。)
  • @molbdnilo 我已经在帖子中添加了。

标签: c++ windows


【解决方案1】:

在日志文件中,我找到了这一行:

[Error]: post message in Mouse move failed. Error: 0

返回的“0”到底是什么意思?

什么都没有。你在if 语句的末尾有一个错误的;,所以PostMessageA() 返回的值无关紧要,因为LogError() 将被无条件地调用 并被传递一个不确定 GetLastError() 值,恰好发生为 0。

你需要摆脱那个;

if (PostMessageA(mainGameWnd, WM_MOUSEMOVE, wParamRawMouse, MAKELPARAM(_mouse_position.x, _mouse_position.y)) == 0)
{
    // error logging
    LogError("post message in Mouse move failed. Error: %ld", GetLastError());
}

现在,话虽如此:

这是否意味着 PostMessageA 失败,我应该检查发送到其中的参数,还是只是消息已成功处理,而我无需执行任何操作?

使用 正确 错误检查,返回值 0 表示 PostMessageA() 本身失败。消息的返回值不会返回给您。只有SendMessage....() 函数可以做到这一点。

【讨论】:

  • 谢谢!我是多么愚蠢!顺便问一下,如何获取特定消息的返回值?改用sendmessage
  • @DerekLu 是的,您必须改用SendMessage()。但并不是所有的消息都是要发送的,也不是所有发布的消息都在窗口过程中处理,所以发送一个要发布的消息可能不会得到你想要的结果。
【解决方案2】:

PostMessage 是异步的。它只能将消息排队到 HWND 的线程中。 PostMessage 的成功返回值表明消息已排队,未服务或处理。所以处理程序没有返回值返回给调用者。

PostMessage 只能在以下情况下失败:

  • hwnd 无效
  • 没有与指定线程关联的消息队列(如果您有 HWND,这几乎是不可能的)
  • 队列已满

SendMessage 是同步的,将返回给定 hwnd/msg 对的消息处理程序的结果。它直接调用 wndproc 消息处理程序(或在线程之间等待它返回)并将返回值返回给调用者。

我不确定您真正想要做什么,但请考虑一下:

  1. 您真的需要来自 PostMessage、SendMessage 或相关处理程序的返回值吗?

  2. 发布WM_MOUSEMOVE 是一件很奇怪的事情。它实际上并没有移动鼠标光标。它只是通知应用程序鼠标光标移动了(如果它有兴趣监听该事件)。在实际系统级别,许多鼠标消息既不发布也不发送。它们是由于线程调用GetMessage 并观察鼠标位置状态自上次调用以来发生变化而动态生成的。

【讨论】:

  • 感谢您的回答。 1.我只是想检查一下PostMessage是否成功。 2.在我的项目中,我hook了一些鼠标相关的Windows api,并尝试向游戏进程发送鼠标和键盘消息。
  • 那我能说检查postmessage的返回值没有意义吗?
  • 检查PostMessage的返回值是否有用,只有你自己决定。
  • PostMessage 失败的情况很少见,但也有可能发生。所以你必须决定它是否是你想要做的事情,如果它失败了。
  • 在我上面帖子的例子中,postmessage返回0。我可以确认postmessage失败吗?
猜你喜欢
  • 2021-09-30
  • 2020-12-10
  • 2016-11-24
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
  • 2015-11-15
  • 2011-02-03
  • 1970-01-01
相关资源
最近更新 更多