原文:http://www.cnblogs.com/lzjsky/articles/1777848.html
函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,并且,如果指定的窗口属于不同的线程,直到窗口程序处理完消息或指定的超时周期结束函数才返回。如果接收消息的窗口和当前线程属于同一个队列,窗口程序立即调用,超时值无用。
函数原型:LRESULT SendMessageTimeout(HWND hwnd,UINT Msg,WPARAM wParam,LPARAM IParam,UINTfuFlags,UIUT uTimeout,LPDWORD lpdwResultult);
参数:
hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息指定信息。
IParam:指定附加的消息指定信息。
fuFlags;指定如何发送消息。此参数可为下列值的组合:
SMTO_ABORTIFHUNG:如果接收进程处于“hung”状态,不等待超时周期结束就返回。
SMTO_BLOCK:阻止调用线程处理其他任何请求,直到函数返回。
SMTO_NORMAL:调用线程等待函数返回时,不被阻止处理其他请求。
SMTO_NOTIMEOUTIFNOTHUNG:Windows 95及更高版本:如果接收线程没被挂起,当超时周期结束时不返回。
uTimeout:为超时周期指定以毫秒为单位的持续时间。如果该消息是一个广播消息,每个窗口可使用全超时周期。例如,如果指定5秒的超时周期,有3个顶层窗回未能处理消息,可以有最多15秒的延迟。
IpdwResult:指定消息处理的结果,依赖于所发送的消息。
返回值:如果函数调用成功,返回非零值。如果函数调用失败,或超时,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。如果GetLastError返回零,表明函数超时。如果使用HWND_BROADCAST,SenddMessaggTimeout不提供单个窗口超时信息。
SendMessageTimeout并不是简单在SendMessage加上Timeout的功能。
MSDN上面有一段文字是这样说的
If the specified window was created by the calling thread, the window procedure is called immediately as a subroutine. If the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message. However, the sending thread will process incoming nonqueued messages while waiting for its message to be processed. To prevent this, use SendMessageTimeout with SMTO_BLOCK set. For more information on nonqueued messages, see Nonqueued Messages.
翻译一下:
SendMessage : 如果指定窗口由调用线程创建,那么窗口过程会被当成一个子程序立即调用。如果指定窗口由另外一个线程创建,那么系统会切换到那个线程,并且调用合适的窗口过程。在线程之间传递的消息仅仅当接收线程执行message retrieval code才会被处理。发送线程会被堵塞直到接收线程处理完消息。但是,发送线程在等待的同时会处理收到的nonqueued messages 。为了阻止这一点,使用带有SMTO_BLOCK参数 的SendMessageTimeout .
=================================华丽的分割线===========================
我曾经遇到这个问题,我调用SendMessage向另外一个线程窗口发message,本来以为他会一直block住,但是他却调用了另外一个消息的处理程序,导致了行为不正确。所以一定要小心使用SendMessage发给其他线程的窗口。
我修改了一下,把
pWnd->SendMessage(MSG_LOG_MESSAGE, nMsgType, (LPARAM)(LPCTSTR)m_cstrMessage);
改成了
HWND hWnd = pWnd->GetSafeHwnd();
::SendMessageTimeout(hWnd,MSG_LOG_MESSAGE, nMsgType, (LPARAM)(LPCTSTR)m_cstrMessage,SMTO_BLOCK,15000,0);
解决了这个bug.