How can you tell if SendMessage() was successful (message was delivered)?

后端 未结 2 1751
别跟我提以往
别跟我提以往 2021-01-25 00:26

is it possible to determine if a SendMessage() call was successful and delivered my message to the target window?

The SendMessage() description in the Windows API seems

相关标签:
2条回答
  • 2021-01-25 00:41

    if SendMessage fail, it set last win32 error code, which we can get back via call GetLastError(). and returned error code, in case fail, never will be 0 (NOERROR) despite this is clear not documented. but how detect that SendMessage is fail ? here we can not base on return value. but we can SetLastError(NOERROR) before call SendMessage and check GetLastError() after:

    • if SendMessage fail - value returned by GetLastError() will be not 0. (most common in this case ERROR_INVALID_WINDOW_HANDLE or ERROR_ACCESS_DENIED).
    • if we still got 0 as last error - this mean that message was delivered with no error.
    • however, possible case, when during SendMessage call, some window procedure in current thread will be called and code inside window procedure, set last error to non 0 value. so we get finally not 0 last error, but not because SendMessage fail. distinguish between these two cases very problematic

    -

        SetLastError(NOERROR);
        LRESULT lr = SendMessageW(hwnd, *, *, *);
        ULONG dwErrorCode = GetLastError();
        if (dwErrorCode == NOERROR)
        {
            DbgPrint("message was delivered (%p)\n", lr);
        }
        else
        {
            DbgPrint("fail with %u error\n", dwErrorCode);
        }
    
    0 讨论(0)
  • 2021-01-25 00:50

    There is no way to reliably tell, whether a call to SendMessage succeeded or failed. After all, it only has a single return value, and the entire range of values is used. There is no designated error value.

    Playing tricks with the calling thread's last error code won't work either. The scheme proposed in this answer (clearing the last error code prior to the call and evaluating it after the call) is brittle. It's easy to see that it can fail, when sending a message to a window owned by the calling thread (as that window's window procedure is at liberty to change the last error any way it sees fit).

    It's not quite as well known, that this can also fail when sending a message to a window owned by a different thread. The code suggests, that no intervening API call can happen in the calling thread. Yet in that scenario, SendMessage will also dispatch incoming cross-thread messages (see When can a thread receive window messages?), allowing the thread's last error code to change.

    The only option then is to use SendMessageTimeoutW, as that API reports both the result of the call, as well as an error/success indicator. Passing the SMTO_NOTIMEOUTIFNOTHUNG flag makes sure that an arbitrarily chosen timeout will not adversely affect the outcome.

    0 讨论(0)
提交回复
热议问题