CMultimediaTimer
CMultimediaTimer implements a simple periodic timer using the Windows Multimedia Timer API.
NB.A Multimedia timer is actually a seperate high priority thread so all the normal multithreading issues apply. As with worker threads, MFC objects should not be called directly from a timer callback due to the Handle Map hoodoo stored in the CWinThread local storage.
CMultimediaTimer is not GUI specific as I use it to handle periodic activity in console applications.
To start a timer
- derive a loop handler class from
CMultimediaTimerCallback overiding the OnLoop() pure virtual method
- create a
CMultimediaTimer passing an instance of the derived loop handling class as the constructor parameter.
- call the
Start() method with the loop period in milliseconds as the first parameter.
Usage example
MyLoopHandlerClass handler;
CMultimediaTimer timer(handler);
timer.Start(20,1);
Classes
CMultimediaTimerCallback is the callback interface that must be overidden to support loop handling.
We seperate loop handling from the main timer class to prevent calls from within OnLoop() accidently calling CMultimediaTimer methods which could cause a race condition.
class CMultimediaTimerCallback
{
public:
CMultimediaTimerCallback(){}
virtual ~CMultimediaTimerCallback(){}
public:
virtual bool OnLoop()=0; virtual void OnStarted(){} virtual void OnStopped(){} };
CMultimediaTimer is the timer class.
To use simply derive a class from CMultimediaTimer and override OnLoop(). Next, call the Start method with the period in milliseconds as the first parameter.
class CMultimediaTimer
{
public:
CMultimediaTimer(CMultimediaTimerCallback& callback);
virtual ~CMultimediaTimer();
bool Start(UINT nPeriodMs,
MMRESULT& nError,
UINT nResolutionMs = cDefaultTimerResolution);
bool Start(UINT nPeriodMs,UINT nResolutionMs = cDefaultTimerResolution)
{MMRESULT nErr; return Start(nPeriodMs,nErr,nResolutionMs);}
void Stop();
bool Active()const {return m_TimerId != 0;}
UINT GetPeriodMs()const {return m_TimerPeriod;}
UINT GetResolutionMs()const{return m_TimerResolution;}
private:
bool CheckMarker()const;
void ResetPeriodResolution();
void DoLoop();
private:
CMultimediaTimerCallback& m_Callback; UINT m_TimerPeriod; UINT m_TimerResolution; UINT m_TimerId; bool m_EndTimer; FLCriticalSection m_StopCriticalSection;
private:
DWORD m_Marker; friend void CALLBACK mmTimerProc(UINT,UINT,DWORD,DWORD,DWORD); };
Happy looping!
John Curtis runs Fatlab Software Pty. Ltd. which provides software services to companies in Perth, Australia and is currently developing a range of productivity apps.
He has 10+ years experience writing C++ software and 3 years writing Java code.
Specialities include STL, Boost, XML, OpenGL, Realtime control, Embedded Linux, Windows CE....