I am writing a MFC application and need to have the program pause for a few seconds. I am trying to use the OnTimer event and am having troubles. The following code causes the program to freeze and stop responding

m_iCount = 0;
	SetTimer(ID_TEST_TIMER, 1000, NULL);
	while(m_iCount <= 5)
	{
         }

However if I add the following it works fine.

m_iCount = 0;
	SetTimer(ID_TEST_TIMER, 1000, NULL);
	while(m_iCount <= 5)
	{
		CString x;
		x.Format("%d",m_iCount);
		MessageBox(x);
	}

In both of these examples the program is suppose to wait 5 seconds before continuing. Also note that m_iCount is suppose to incrament everytime the ID_TEST_TIMER event is called. Any suggestions on what I am doing wrong and can do to fix it?

Dani AI

Generated

— the root problem in your first post is that the UI thread was being kept busy (a busy-wait), so Windows never got a chance to deliver the timer message. correctly called out the infinite loop, and was also right to hint that Sleep() is the wrong tool for an interactive timeout because it blocks message processing.

A simple, responsive pattern is: start a one-second timer when the edit becomes active, decrement a seconds-left counter in OnTimer, update a label, and when the counter reaches zero kill the timer and disable the edit. This keeps the message pump running so the UI stays responsive and the timer actually fires.

// start countdown (e.g. button handler)
m_secondsLeft = 20;
GetDlgItem(IDC_MYEDIT)->EnableWindow(TRUE);
SetTimer(101, 1000, NULL);

// OnTimer handler in your dialog
void CMyDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == 101)
    {
        if (--m_secondsLeft <= 0)
        {
            KillTimer(101);
            GetDlgItem(IDC_MYEDIT)->EnableWindow(FALSE);
            GetDlgItem(IDC_STATIC_TIMER)->SetWindowText(_T("0"));
        }
        else
        {
            CString s;
            s.Format(_T("%d"), m_secondsLeft);
            GetDlgItem(IDC_STATIC_TIMER)->SetWindowText(s);
        }
    }
    CDialog::OnTimer(nIDEvent);
}

Notes: always KillTimer when done, use a unique ID, keep OnTimer work short, and never block the UI thread. For high-precision timing or long background work, use a worker thread and PostMessage back to the UI instead of doing heavy work inside OnTimer.

Recommended Answers

All 5 Replies

while(m_iCount <= 5)
	{
         }

How many ways can you say infinite loop ? and it is consuming nearly all CPU time?

why are you making it so difficult ? If you goal is for the program to pause for 5 second, just call Sleep() function. No need for that timer.

Why? Becasue I am a noob who forgot about Sleep();
Thanx for the help!!:o

Ok, so here's a spin off of the previous. If I wanted the user to only have say 20 seconds to enter text in an edit box before it grayed out, how would I go about that?

Sleep()

causes the program to pause, so what would I use?

Why don't you read the documentation for Sleep() ????

Ok, so here's a spin off of the previous. If I wanted the user to only have say 20 seconds to enter text in an edit box before it grayed out, how would I go about that?

Sleep()

causes the program to pause, so what would I use?

You can't use Sleep() in that situation because Sleep will not allow the user to do anything during that time. I have not tried it but I think you can use sometime like this example which is implements a timeout for MessageBox. In a nutshell, you set a timer to kick off in 20 seconds. In the timer event check of the user has typed anything in the edit control and if not then send the control a WM_CLOSE message.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.