Timers in MFC / C++






4.20/5 (5 votes)
Jan 17, 2006

94747
Implementing one-shot timers.
Introduction
Setting a timer in C++/Win32 that fires once, normally requires a lot of work, considering that all you really want to do is wait a bit and execute a function, but not block mainline code execution. This simple class makes OneShot timers easy. No more struggling with static functions and 'this
' pointers.
Using the code
The only special instructions for using this class are:
- You must instantiate the timer object using
new
, because the object deletes itself after the timer fires. - The target function is called using
PostMessage
, so there must be aMESSAGE_MAP
entry (eitherON_MESSAGE
, orON_COMMAND
) for the target function.
// Map the function you want to call. // You can use either Command or Message format: BEGIN_MESSAGE_MAP(CMyClass, CWnd) ON_COMMAND( IDC_DOCOMMAND, OnDoCommand ) ON_MESSAGE( IDC_DOMESSAGE, OnDoMessage ) END_MESSAGE_MAP()
// Your Functions void CMyClass::OnDoCommand() { return; } LRESULT CMyClass::OnDoMessage( WPARAM wParam, LPARAM lParam ) { return 0; }
// In your code, fire the OneShots. Remember they must use new, as //they are self deleting once the timer fires. //The TimerID is guaranteed to be unique as the object //exists for the the duration of the timer. new CTimerOneShot( 2000, GetSafeHwnd(), IDC_DOCOMMAND ); // Command Version // or new CTimerOneShot( 2000, GetSafeHwnd(), IDC_DOMESSAGE, 123, 456 ); // Message Version
// And here is the OneShot class. #pragma once class CTimerOneShot { public: // MESSAGE Format CTimerOneShot( int a_msecs, HWND a_targetHwnd, int a_messageID, WPARAM a_wparam, LPARAM a_lparam ) { m_timerID = (UINT) this; m_targetHwnd = a_targetHwnd; m_messageID = a_messageID; m_lparam = a_lparam; m_wparam = a_wparam; m_msecs = a_msecs; ::SetTimer( a_targetHwnd, m_timerID, m_msecs, TimerProcA ); } static void CALLBACK EXPORT TimerProcA( HWND a_hwnd, UINT /*WM_TIMER*/, UINT a_timerID, DWORD a_systemtime ) { CTimerOneShot* pOneShot = (CTimerOneShot*) a_timerID; ASSERT( a_hwnd == pOneShot->m_targetHwnd ); ::KillTimer( pOneShot->m_targetHwnd, a_timerID ); ::PostMessage( pOneShot->m_targetHwnd, pOneShot->m_messageID, pOneShot->m_wparam, pOneShot->m_lparam ); delete pOneShot; } // COMMAND Format CTimerOneShot( int a_msecs, HWND a_targetHwnd, int a_commandID ) { m_timerID = (UINT) this; m_targetHwnd = a_targetHwnd; m_commandID = a_commandID; m_msecs = a_msecs; ::SetTimer( a_targetHwnd, m_timerID, m_msecs, TimerProcB ); } static void CALLBACK EXPORT TimerProcB( HWND a_hwnd, UINT /*WM_TIMER*/, UINT a_timerID, DWORD a_systemtime ) { CTimerOneShot* pOneShot = (CTimerOneShot*) a_timerID; ASSERT( a_hwnd == pOneShot->m_targetHwnd ); ::KillTimer( pOneShot->m_targetHwnd, a_timerID ); ::PostMessage( pOneShot->m_targetHwnd, WM_COMMAND, pOneShot->m_commandID, 0 ); delete pOneShot; } HWND m_targetHwnd; int m_messageID; int m_commandID; LPARAM m_lparam; WPARAM m_wparam; UINT m_timerID; int m_msecs; };