消息处理(二):投递与发送
2013-07-15 15:59
155 查看
消息的投递(Post)过程类似于普通信件的投递过程。普通信件通过邮递员到达收信方的信箱里,收信方取得该信,阅读信件内容,并可能回信。在这个过程中,邮递员的责任只是将信件送到收信者的信箱,一切任务就完成了。
消息的发送(Send)过程理解为打电话交流的过程。甲找到乙的电话号码,然后开始拨号。如果运气好,拨通了乙的电话,那么两人就联系上了。假设甲方从不主动挂断电话,那么只有乙方先挂断电话,两人的一次联系才宣告结束。
PostMessage函数
CWnd::PostMessage提供了对PostMessage的简单包装,他首先断言窗口句柄表示一个窗口,然后以窗口句柄为第一个参数调用全局的PostMessage:
hWnd有两个特殊的值:HWND_BROADCAST和NULL。前者表示要将该消息投递到系统当前所有的非子窗口。后者表示由线程而不是某个窗口的窗口过程来处理该消息。
Msg表示投递的消息标志,最后两个参数则表示特定于该消息的参数。千万要注意,因为投递消息类似于异步调用,所以在消息参数中传递指针是非常危险。
SendMessage函数
可以将hWnd的参数设置为HWND_BROADCAST,表示系统所有的非子窗体广播此消息。
为了避免调用线程陷入永久的等待状态,可以用SendMessageTimeout代替SendMessage:
关键是fuFlag参数,它决定了该如何发送该消息,fuFlag参数的值及含义如下表:
如果调用成功,SendMessageTimeout会返回非0值;如果调用失败或发生超时,则返回0。为了防止调用线程被无限等待,可以将fuFlag参数设为SMTO_BLOCK,并设置一定的超时时间。
说明:如果是广播消息,假定有两个目标窗口将处理该消息,那么目标线程将总共有2*uTimeout毫秒的等待期。
CWnd::SendMessage对SendMessage进行了简单的包装,它验证窗口句柄的有效性,然后调用SendMessage API函数:
提示:CWnd没有提供对SendMessageTimeout的包装。
同属于SendMessage系列的API还有SendNotifyMessage和SendMessageCallback,其行为特性介于PostMessage和SendMessage之间。
SendNotifyMessage函数:
如果hWnd窗口由调用线程创建,那么其行为特性跟SendMessage相同,这时将等待消息处理完毕后才返回。如果hWnd由另一线程创建,其行为特性则与PostMessage相同,它不必等待目标线程处理完该消息而直接返回。
SendMessageCallback函数:
SendMessageCallback的行为特性类似于PostMessage,也是在发出消息后,不等待目标窗口处理该消息就立刻返回,但它允许消息处理完毕后,让系统执行指定的函数。
SENDASYNCPROC是回调函数的类型,它具有如下形式的签名:
传入回调函数的dwData正是在SendMessageCallback中的dwData参数指定的。
消息的发送(Send)过程理解为打电话交流的过程。甲找到乙的电话号码,然后开始拨号。如果运气好,拨通了乙的电话,那么两人就联系上了。假设甲方从不主动挂断电话,那么只有乙方先挂断电话,两人的一次联系才宣告结束。
PostMessage函数
BOOL PostMessage( HWND hWnd, //目标窗口句柄 UINT Msg, //消息 WPARAM wParam, //第一个消息参数 LPARAM lParam //第二个消息参数 );
CWnd::PostMessage提供了对PostMessage的简单包装,他首先断言窗口句柄表示一个窗口,然后以窗口句柄为第一个参数调用全局的PostMessage:
_AFXWIN_INLINE BOOL CWnd::PostMessage(UINT message, WPARAM wParam, LPARAM lParam) { ASSERT(::IsWindow(m_hWnd)); return ::PostMessage(m_hWnd, message, wParam, lParam); }
hWnd有两个特殊的值:HWND_BROADCAST和NULL。前者表示要将该消息投递到系统当前所有的非子窗口。后者表示由线程而不是某个窗口的窗口过程来处理该消息。
Msg表示投递的消息标志,最后两个参数则表示特定于该消息的参数。千万要注意,因为投递消息类似于异步调用,所以在消息参数中传递指针是非常危险。
SendMessage函数
LRESULT SendMessage( HWND hWnd, //接收消息的目标窗口 UINT Msg, //消息标志 WPARAM wParam, //第一个消息参数 LPARAM lParam //第二个消息参数 );
可以将hWnd的参数设置为HWND_BROADCAST,表示系统所有的非子窗体广播此消息。
为了避免调用线程陷入永久的等待状态,可以用SendMessageTimeout代替SendMessage:
LRESULT SendMessageTimeout( HWND hWnd, //窗口句柄 UINT Msg, //消息标记 WPARAM wParam, //第一个消息参数 LPARAM lParam, //第二个消息参数 UINT fuFlags, //消息发送选项 UINT uTimeout, //超时,以毫秒为单位 PDWORD_PTR lpdwResult, //返回值,依赖于特定的消息 );
关键是fuFlag参数,它决定了该如何发送该消息,fuFlag参数的值及含义如下表:
值 | 说 明 |
SMTO_ABORTIFHUNG | 如果目标线程处于挂起状态,调用线程将不等待超时而立即返回 |
SMTO_BLOCK | 阻止调用线程在目标线程处理完消息之前处理其他请求 |
SMTO_NORMAL | 在等待目标线程处理消息时,允许调用线程处理其他请求 |
SMTO_NOTIMEOUTIFNOTHUNG | 对于XP/WIN2000有意义:如果目标线程未挂起,调用线程即使发生超时也会等待目标线程处理完该消息 |
说明:如果是广播消息,假定有两个目标窗口将处理该消息,那么目标线程将总共有2*uTimeout毫秒的等待期。
CWnd::SendMessage对SendMessage进行了简单的包装,它验证窗口句柄的有效性,然后调用SendMessage API函数:
_AFXWIN_INLINE LRESULT CWnd::SendMessage(UINT message, WPARAM wParam, LPARAM lParam) { ASSERT(::IsWindow(m_hWnd)); return ::SendMessage(m_hWnd, message, wParam, lParam); }
提示:CWnd没有提供对SendMessageTimeout的包装。
同属于SendMessage系列的API还有SendNotifyMessage和SendMessageCallback,其行为特性介于PostMessage和SendMessage之间。
SendNotifyMessage函数:
BOOL SendNotifyMessage( HWND hWnd; //窗口句柄 UINT Msg; //消息标志 WPARAM wParam, //第一个消息参数 LPARAM lParam //第二个消息参数 );
如果hWnd窗口由调用线程创建,那么其行为特性跟SendMessage相同,这时将等待消息处理完毕后才返回。如果hWnd由另一线程创建,其行为特性则与PostMessage相同,它不必等待目标线程处理完该消息而直接返回。
SendMessageCallback函数:
SendMessageCallback的行为特性类似于PostMessage,也是在发出消息后,不等待目标窗口处理该消息就立刻返回,但它允许消息处理完毕后,让系统执行指定的函数。
BOOL SendMessageCallback( HWND hWnd, //窗口句柄 UINT Msg, //消息标志 WPARAM wParam, //第一个消息参数 LPARAM lParam, //第二个消息参数 SENDASYNCPROC lpCallBack, //回调函数 ULONG_PTR dwData //应用范围内的数据 );
SENDASYNCPROC是回调函数的类型,它具有如下形式的签名:
VOID CALLBACK SendAsyncProc( HWND hwnd, //目标窗口的句柄 UINT uMsg, //消息标记 ULONG_PTR dwData, //应用范围的数据 LRESULT lResult //消息处理结束,依赖于特定的消息 );
传入回调函数的dwData正是在SendMessageCallback中的dwData参数指定的。
相关文章推荐
- kafka无法发送消息问题处理
- PHP处理微信中带Emoji表情的消息发送和接收(Unicode字符转码编码)
- QT中用udp客户端发送消息,丢失数据的情况以及处理!
- DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM
- 如何在Qt中处理(接收/发送)MFC或Windows消息(message)
- JAX-WS创建和JavaAPI发送和处理SOAP消息实例
- Android: 如何利用Handler处理和发送消息来实现页面刷新的功能
- 异常信息:CLR无法从COM 上下文0x645e18 转换为COM上下文0x645f88,这种状态已持续60秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作.这种情况通常会影响到性能,甚至可能导致应用程序不响应或者使用的内存随时间不断累积
- 主线程利用MsgWaitForMultipleObjects等待子线程结束时,同时处理子线程发送的窗口消息
- 如何处理在android中有来电就给来电用户发送一个消息?
- WebSocket发送消息,大于126字节和大于65535字节的处理
- EventBus---消息的发送与处理(一)
- PHP处理微信中带Emoji表情的消息发送和接收(Unicode字符转码编码)
- ListCtrl列表控件中NM_CLICK消息的发送和处理一例
- 微信公共号开发教程java版——发送消息和处理消息(四)
- Handler发送消息后消息队列的处理
- PHP处理微信中带Emoji表情的消息发送和接收(Unicode字符转码编码)
- WebViewJavascriptBridge 分析oc向js发送消息处理流程
- java.lang.RuntimeException: 将消息发送到死的线程上处理程序的处理程序 (android.os.Handler)
- Disruptor多个消费者不重复处理生产者发送的消息的demo