今天把SendMessage与PostMessage研究了一把,如下:~
一、SendMessage
将指定的消息发送到一个或多个窗口,该函数为指定的窗口调用窗体程序,直到窗体程序处理完消息再返回。
语法声明:
LRESULT WINAPI SendMessage( _in HWND hWnd, _in UINT Msg, _in WPARAM wParam, _in LPARAM lParam);
参数:
hWnd [in]: 型别:HWND
其窗体程序将接收消息的窗口的句柄。如果这个参数为HWND_BROADCAST((HWND)0xffff),消息被发送到系统中所有的顶级窗口,包括无效或不可见的无主窗口,重叠窗体和弹出窗体;但是消息不会被发送到子窗口。
Msg [in]:型别:UINT
被发送的消息。
wParam [in]:型别:WPARAM
附加的消息指定信息
lParam [in]:型别:LPARAM
附加的消息指定信息
返回值:
型别:LRESULT
返回值指定了消息的处理结果,他取决于所发送的消息。
备注:
当一条消息被UIPI(用户界面特权隔离)阻塞,由GetLastError获得的最后错误被设置为5(拒绝访问)。
需要用HWND_BROADCAST通信的应用应该使用RegisterWindowsMessage函数获得唯一的消息,该消息来用于内部应用通信。
系统只整编(marshal)系统消息(0 到WM_USER-1之间的消息),发送用户消息(WM_USER 以上)到别的进程时,需要自己做整编。
如果指定的窗口是由正在调用的线程创建的,窗体程序作为子线程立马被调用。如果指定的窗口是由不同的线程创建的,那么系统切换到那个线程并调用相应的窗体程序。只有当接收线程执行消息重获代码时,在线程间传送的消息才被处理。发送线程一直被阻塞直到接收线程处理消息。然而,发送线程在等待他的消息被处理的过程中,他将处理来临的非队列消息。为了防止这种情况发生,使用SendMessageTimeout+SMTO_BLOCK设置。
二、SendMessage
将消息发送到与线程有关的消息队列中,该线程创建了指定的窗口。不等线程处理完消息就返回。

 语法声明:

BOOL WINAPI PostMessage( _in_opt HWND hWnd, _in UINT Msg, _in WPARAM wParam, _in LPARAM lParam);
参数:(同SendMessage)
返回值:
型别:BOOL
如果函数成功返回,返回值非0;如果函数返回失败,返回值为0。如要获得额外的错误信息,调用GetLastError
备注:
当一条消息被UIPI(用户界面特权隔离)阻塞,由GetLastError获得的最后错误被设置为5(拒绝访问)。
在消息队列中的消息用过GetMessage或者PeekMessage函数获得。
需要用HWND_BROADCAST通信的应用应该使用RegisterWindowsMessage函数获得唯一的消息,该消息来用于内部应用通信。
系统只整编(marshal)系统消息(0 到WM_USER-1之间的消息),发送用户消息(WM_USER 以上)到别的进程时,需要自己做整编。
用 PostMessage、SendNotifyMessage、SendMessageCallback 等异步函数发送系统消息时,参数里不可以使用指针,否则操作将会失败。因为发送者并不等待消息的处理就返回,接受线程还没处理消息指针就已经被释放了。
不要使用PostMessage发送WM_QUIT消息,用PostQuitMessage函数。
在 Windows 2000/XP 里,每个消息队列最多只能存放10,000 个Post 的消息,这个数量应该是足够大的。超过的还没被处理的将不会被处理,直接丢掉。这个值可以改得更大:[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows] USERPostMessageLimit,最小可以是 4000。
三、总结
  1. 4 个参数的意义是一样的,返回值类型不同(其实从数据上看他们一样是一个 32 位的数,只是意义不一样),LRESULT 表示的是消息被处理后的返回值,BOOL 表示的是消息是不是Post 成功。
  2. PostMessage 是异步的,SendMessage 是同步的。PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而SendMessage 等待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。
  3. 如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。
  4. 如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它SendMessage。Post 到别的线程时,最好用PostThreadMessage 代替 PostMessage,PostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage + GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。
posted on 2011-11-03 18:54  润德  阅读(3546)  评论(0编辑  收藏  举报