这个问题,我搞了好久.
其实很简单,给一个线程发消息 PostThreadMessage().
BOOL PostThreadMessage(
DWORD idThread, // thread identifier {这个参数为线程ID,不是线程句柄}
UINT Msg, // message to post
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
eg:
int ret = PostThreadMessage( pThread->m_nThreadID, WM_SPLASH_NOTIFY,0, 0 );
if (ret == 0) // :检查返回值,是否失败.
{
//AfxMessageBox("post thread msg error!");
if ( ERROR_INVALID_THREAD_ID == GetLastError() )
{
AfxMessageBox("无效thread ID(你是否把线程句柄传了进去?:))! 或者线程里面没有消息泵!!!");
}
}
WM_SPLASH_NOTIFY是自己定义的一个常量, 可以不用加入消息映射 呵呵. 直接在UI线程的PreTranslateMessage里面捕获处理就好了.:), 当然, 通过MFC的宏加入消息处理函数也可以, 不过原理是一样的.
, 那么主线程如何知道UI界面线程的ID呢?
答案是: 通过AfxBeginThread()函数创建线程时, 返回CWinThread* pThead指针.
AfxBeginThread()返回一个CWinThread*对象指针,
CWinThread* pThread = AfxBeginThread(...) ;
pThread->m_nThreadID就是创建线程的ID.
特别注意 , pThead->m_hThread是线程的句柄!!!! 不可以作为PostThreadMessage()的参数,否则会提示: error C2664: 'PostThreadMessageA' : cannot convert parameter 1 from 'void *' to 'unsigned long' 编译错误.
具体参见如下帖子.
http://topic.csdn.net/t/20040509/14/3045752.html
那么我们发了消息后, 用户界面线程如何处理消息呢?
重载PreTranslateMessage()函数.
BOOL CUIThread::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message == WM_SPLASH_NOTIFY )
{
AfxMessageBox("catch!");
}
return CWinThread::PreTranslateMessage(pMsg);
}
补充说明两点
1: 线程ID 不同于线程句柄, ID可用于给线程发消息.
2: 线程句柄 可用于控制线程的执行,比如, 关闭线程, 暂停线程啥的.
也就是通常意义上的UI界面线程, 可以给该线程发消息. 呼呼.
3,4的说法可能有问题,已经测试过,对于工作线程, 已经测试过, 不可以在工作线程里面peekmessage.(peekmessage总是返回false, peek不到message ), .但是可以work thread成功发送消息, 但work thread里面 peekmessage老是失败.不知道CWinThread做了什么手脚.呼呼.
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
参见msdn. PostThreadMessage的解释.
下面文章是codeproject上详细讲解用户界面线程原理的文章.