在响应一个按钮消息的时候,我用下面的代码等待一个线程的结束:while (true)
{
result_wait = ::MsgWaitForMultipleObjects(1, (HANDLE *)&_id, FALSE, INFINITE, QS_ALLINPUT); if (WAIT_OBJECT_0 + 1 == result_wait)
{
// Get next message in queue.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
else //if ( ( dwRet >= WAIT_OBJECT_0) && ( dwRet < WAIT_OBJECT_0 + 1) )
{
// Thread just ended.
ajust_status();
break;
}
}但是这里的 ::TranslateMessage(&msg); ::DispatchMessage(&msg); 却相应不了消息循环中的PreTranslateMessage了,那么在PreTranslateMessage里处理消息就无法得到执行。怎么解决冲突啊?

解决方案 »

  1.   

    还是多线程吧,这么用MsgWaitForMultipleObjects容易出问题。
    参考 http://blogs.msdn.com/b/oldnewthing/archive/2005/02/17/375307.aspx
      

  2.   


    谢谢给的参考,收益匪浅,但我用while循环把消息处理完之后再去等的,应该没问题吧。
      

  3.   

    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
                    {
                        ::TranslateMessage(&msg);
                        ::DispatchMessage(&msg);
                    }
    你自己写的消息环根本没调用PreTranslateMessage,当然运行不了了。你去看看人家MFC的消息环怎么写的:int CWinThread::Run()
    {
    ASSERT_VALID(this); // for tracking the idle time state
    BOOL bIdle = TRUE;
    LONG lIdleCount = 0; // acquire and dispatch messages until a WM_QUIT message is received.
    for (;;)
    {
    // phase1: check to see if we can do idle work
    while (bIdle &&
    !::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
    {
    // call OnIdle while in bIdle state
    if (!OnIdle(lIdleCount++))
    bIdle = FALSE; // assume "no idle" state
    } // phase2: pump messages while available
    do
    {
    // pump message, but quit on WM_QUIT
    if (!PumpMessage())
    return ExitInstance(); // reset "no idle" state after pumping "normal" message
    if (IsIdleMessage(&m_msgCur))
    {
    bIdle = TRUE;
    lIdleCount = 0;
    } } while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
    } ASSERT(FALSE);  // not reachable
    }BOOL CWinThread::PumpMessage()
    {
    ASSERT_VALID(this); if (!::GetMessage(&m_msgCur, NULL, NULL, NULL))
    {
    #ifdef _DEBUG
    if (afxTraceFlags & traceAppMsg)
    TRACE0("CWinThread::PumpMessage - Received WM_QUIT.\n");
    m_nDisablePumpCount++; // application must die
    // Note: prevents calling message loop things in 'ExitInstance'
    // will never be decremented
    #endif
    return FALSE;
    }#ifdef _DEBUG
    if (m_nDisablePumpCount != 0)
    {
    TRACE0("Error: CWinThread::PumpMessage called when not permitted.\n");
    ASSERT(FALSE);
    }
    #endif#ifdef _DEBUG
    if (afxTraceFlags & traceAppMsg)
    _AfxTraceMsg(_T("PumpMessage"), &m_msgCur);
    #endif // process this message if (m_msgCur.message != WM_KICKIDLE && !PreTranslateMessage(&m_msgCur))
    {
    ::TranslateMessage(&m_msgCur);
    ::DispatchMessage(&m_msgCur);
    }
    return TRUE;
    }
      

  4.   


    哦,一语惊醒梦中人啊。我总是想等到线程完全结束,其实没必要的,对吗? 只要这么做:
    unsinged ThreadFun
    {
    ...
    ::PostMessage(hWnd, WM_ThreadEnded, 0, 0);
    _endthreadex(0);
    }然后处理该消息的时候就认为线程已经结束了。是这意思吗?
      

  5.   


    是的,保险起见,消息处理线程收到WM_ThreadEnded消息后,最好再调用WaitForSingleObject(hThread),确保线程安全退出。
      

  6.   


    我发现PretranslateMessage只在当前模块中所有的窗口里Walk了一遍。如果我的线程在另外的某块。即便我:
    while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) && ! AfxGetThread()->PreTranslateMessage(&msg))
    {
    ::TranslateMessage(&msg);
    ::DispatchMessage(&msg);
    }也没用,因为这样也Walk不到主模块啊。