消息的投递(Post)过程相似于普通讯件的投递过程。普通讯件经过邮递员到达收信方的信箱里,收信方取得该信,阅读信件内容,并可能回信。在这个过程当中,邮递员的责任只是将信件送到收信者的信箱,一切任务就完成了。异步
消息的发送(Send)过程理解为打电话交流的过程。甲找到乙的电话号码,而后开始拨号。若是运气好,拨通了乙的电话,那么两人就联系上了。假设甲方从不主动挂断电话,那么只有乙方先挂断电话,两人的一次联系才宣告结束。函数
PostMessage函数spa
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函数code
LRESULT SendMessage( HWND hWnd, //接收消息的目标窗口 UINT Msg, //消息标志 WPARAM wParam, //第一个消息参数 LPARAM lParam //第二个消息参数 );
能够将hWnd的参数设置为HWND_BROADCAST,表示系统全部的非子窗体广播此消息。blog
为了不调用线程陷入永久的等待状态,能够用SendMessageTimeout代替SendMessage:回调函数
LRESULT SendMessageTimeout( HWND hWnd, //窗口句柄 UINT Msg, //消息标记 WPARAM wParam, //第一个消息参数 LPARAM lParam, //第二个消息参数 UINT fuFlags, //消息发送选项 UINT uTimeout, //超时,以毫秒为单位 PDWORD_PTR lpdwResult, //返回值,依赖于特定的消息 );
关键是fuFlag参数,它决定了该如何发送该消息,fuFlag参数的值及含义以下表:table
值 | 说 明 |
SMTO_ABORTIFHUNG | 若是目标线程处于挂起状态,调用线程将不等待超时而当即返回 |
SMTO_BLOCK | 阻止调用线程在目标线程处理完消息以前处理其余请求 |
SMTO_NORMAL | 在等待目标线程处理消息时,容许调用线程处理其余请求 |
SMTO_NOTIMEOUTIFNOTHUNG | 对于XP/WIN2000有意义:若是目标线程未挂起,调用线程即便发生超时也会等待目标线程处理完该消息 |
若是调用成功,SendMessageTimeout会返回非0值;若是调用失败或发生超时,则返回0。为了防止调用线程被无限等待,能够将fuFlag参数设为SMTO_BLOCK,并设置必定的超时时间。class
说明:若是是广播消息,假定有两个目标窗口将处理该消息,那么目标线程将总共有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参数指定的。