tags:

views:

1170

answers:

4

In MFC I'm trying to set a null handler timer (ie. no windows). But I'm unable to process the WM_TIMER event in the CWinApp MESSAGE_MAP. Is this possible? If so, how?

+1  A: 

I've done this by making an invisible window and setting a timer on it.

Adam Tegen
+5  A: 

As told by MSDN, there are two modes of operation for SetTimer(): one that associates a timer with a window, and one that associates a timer with a thread's message queue. When you have a window, you can use the former; otherwise, you must use the latter. And CWinApp isn't a window.

Catching timer messages in the thread queue

UINT_PTR uTimerId = SetTimer(NULL, 0, 2000, NULL);
TRACE(_T("Timer created - ID=%x\n"), uTimerId);

This will create a new timer, set to fire every two seconds, associated only with the current thread's message queue. You don't get to specify a timer ID when you aren't associating it with a window, so save the ID returned in a class member or something - you'll have a rough time killing the timer later on if you forget. You could then process this in a CWinApp::PreTranslateMessage() override:

BOOL CMyFunkyApp::PreTranslateMessage(MSG* pMsg)
{
   if (pMsg->message == WM_TIMER)
   {
      TRACE(_T("Timer fired - ID=%x\n"), pMsg->wParam);
   }

   return CWinApp::PreTranslateMessage(pMsg);
}

Note that hooking into the thread's message loop like this is the only way to handle a timer set up this way - as we discussed, there's no window, and although MFC does provide a message map facility for CWinApp you can't use the ON_WM_*() macros because... well, because it's not a window. However, there is another, slightly less-messy way: callbacks.

Handling timer messages with a callback

void CALLBACK TimerCallback(HWND, UINT, UINT_PTR id, DWORD dwTime)
{
   TRACE(_T("Timer fired - ID=%x\n"), id);
}

//...

UINT_PTR uTimerId = SetTimer(NULL, 0, 2000, &TimerCallback);
TRACE(_T("Timer created - ID=%x\n"), uTimerId);

This does almost exactly the same thing as the first example: a new timer is configured to fire every two seconds, associated with the current thread's message queue... but this one has a callback address associated with it. And the default message handler knows to call the callback when such a timer message is processed, so you don't have to bother hooking into the message loop.

So there you go. Two ways of using timers from CWinApp.

Shog9
A: 

Check out this post by Eric Raymond. There are some interesting nuggets for what your working on that might keep you out of trouble.

Why your thread is spending all its time processing meaningless thread timers

John Dyer
A: 

While I second Shog9's answer, I have to ask: Where does the requirement come from? Why is it a problem to associate your timer with a window?

Serge - appTranslator