按照MSDN上的说法,只要把SetTimer的第四个参数设为NULL,当定时器的时间用完时,一个WM_TIMER消息就会被放入消息队列中,之后调用OnTimer函数。MSDN上关于OnTimer的说法是这样的:
The framework calls this member function after each interval specified in the SetTimer member function used to install a timer. 这样看来,只要定时器的时间一到,系统就会调用这个OnTimer函数。所以,我们可以通过override窗口的OnTimer函数来做点事情。在VC技术内幕(第5版)上的例子ex12a,就是一个对话框,上面放了三样东西:一个start按钮和一个cancel按钮,以及一个进度条。 它们之间的关系是这样的:按start,进度条开始走,走完之后对话框自动关闭。按cancel按钮会导致进度条一下子变满,之后关闭对话框。三个相关的函数如下所示:void CComputeDlg::OnStart() 
{
    MSG message;    m_nTimer = SetTimer(1, 100, NULL); // 1/10 second
    ASSERT(m_nTimer != 0);
    GetDlgItem(IDC_START)->EnableWindow(FALSE);
    volatile int nTemp;
    for (m_nCount = 0; m_nCount < nMaxCount; m_nCount++) 
{
if (m_nCount==800) 
{
int a = 1;
}
        for (nTemp = 0; nTemp < 50000; nTemp++) 
{
            // uses up CPU cycles
        }        if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) 
{
            ::TranslateMessage(&message);
            ::DispatchMessage(&message);
        }
    }
    CDialog::OnOK();

}void CComputeDlg::OnTimer(UINT nIDEvent) 
{
    CProgressCtrl* pBar = (CProgressCtrl*) GetDlgItem(IDC_PROGRESS1);
    pBar->SetPos(m_nCount * 100 / nMaxCount);
}void CComputeDlg::OnCancel() 
{
    TRACE("entering CComputeDlg::OnCancel\n");
    if (m_nCount == 0) {      // prior to Start button
        CDialog::OnCancel();
    }
    else {                    // computation in progress
        m_nCount = nMaxCount; // Force exit from OnStart
    }
}
-----------------------------------------------------------------------------------------
我的问题是这样的:
如果去掉OnStart函数中的
        if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) 
{
            ::TranslateMessage(&message);
            ::DispatchMessage(&message);
        }
进度条就不会动了,可这是为什么呢?按照我的理解,只要时间到了,框架就自动调用OnTimer函数,而我自己又做了一个测试,只要执行CProgressCtrl::SetPos进度条就会往前走,既然这样,那么进度条的前进就应该和这个if结构体没有关系,可事实上不是这样的。难道这个WM_TIMER消息不是自动发送的,而是由这个if结构体发送的?还望高人指点,多谢多谢!

解决方案 »

  1.   

    上面函数中用到的数据成员为
    int m_nTimer;
    int m_nCount; //在InitalDialog中设为0
    enum {nMaxCount = 10000};
      

  2.   

    if (::PeekMessage(&message, NULL, 0, 0, PM_REMOVE)) 
    {
                ::TranslateMessage(&message);
                ::DispatchMessage(&message);
            }
    的作用是保持消息的流动,去掉了以后,消息就没办法到达你的窗口过程了,既界面线程执行了那个非常消耗cpu时间的for循环,没办法响应消息。
    WM_TIMER是要通过消息循环才能到达你的窗口过程,如果界面线程执行了那个非常消耗cpu时间的for循环,没办法响应消息,OnTimer函数是不会执行的。
    建议lz看一下《windows程序设计》这本书,了解一下windows的GUI子系统的工作原理
      

  3.   

    根据侯捷《MFC深入浅出》获知内部有一个消息处理循环,
    那么这个循环可以处理WM_TIMER,那么应该即使程序中没有
    这个消息循环处理也应该处理WM_TIMER事件呀?
    哪为什么去掉循环会不行呢?
    学习中???
      

  4.   

    ls的试想一下你在写C程序,需要printf和scanf,main函数在执行scanf调用的时候能否同时执行printf?
    肯定不能,ok
    看一下lz的例子,线程在执行那个非常消耗cpu时间的for循环的时候还会同时执行消息循环么?
      

  5.   

    讲解的有道理,该程序主要是单线程处理,
    我原来错误以为SetTimer后随时可能触发WM_TIMER消息,
    不应该等到函数结束后才触发WM_TIMER,
    I get it,thank you!