基于委托机制的定时器的实现

来源:互联网 发布:单管放大电路实验数据 编辑:程序博客网 时间:2024/06/04 18:33

最近在做Win32开发,要用到多个定时器,由于需要用定时器的对象没有窗口,又不想恶心地先传到窗口再让窗口传给自己,就看看MSDN有没有更好的办法:

下面摘抄MSDN声明部分,原文参考http://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx

SetTimer function

UINT_PTR WINAPI SetTimer(

 __in_opt  HWND hWnd,

 __in      UINT_PTR nIDEvent,

 __in      UINT uElapse,

 __in_opt  TIMERPROC lpTimerFunc

);

 

看了看后面的参数解析,大意是,如果hWnd传一个NULL进去,系统将通过回调函数通知,就是最后一个参数了,并且,此时 nIDEvent也应该为NULL

然后再参考TimerProc:http://msdn.microsoft.com/en-us/library/windows/desktop/ms644907(v=vs.85).aspx

TimerProc

VOID CALLBACK TimerProc(

 __in  HWND hwnd,

 __in  UINT uMsg,

  __in  UINT_PTR idEvent,

 __in  DWORD dwTime

);

 

如果SetTimer时第一个参数传了NULL,这里对我们而言,hwnd == NULL 常数,uMsg == WM_TIMER,常数,idEventSetTimer返回值,有用,dwTimeGetTickCount 得到,意义也不大。并且这里完全无法存放自己的附加数据。于是想到了封装。下面看代码:

 

 

//Timer.h#ifndef Timer_h__#define Timer_h__#include <windows.h>#pragma   warning(disable:4786)#include <MAP>class CTimer;class CTimerDelegate{public:virtual void OnTimer(CTimer *pTimer,LPVOID lParam) = 0;};typedef std::map<UINT,CTimer*>  TIMER_MAP;typedef std::pair<UINT,CTimer*> TIMER_PAIR;class CTimer{private:CTimerDelegate*m_pDelegate;LPVOIDm_lTimerParam;UINTm_nTimerID;private:CTimer(CTimerDelegate*pDelegate);private:static TIMER_MAPm_TimerMap;private:static void CALLBACKTimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);public://SetTimer设置定时器工作模式并启动定时器//参数:nElapse,定时器超时时间(毫秒)//lParam,附加的定时器参数,默认为空void SetTimer(UINT nElapse,LPVOID lParam = NULL);//杀死一个定时器BOOL KillTimer();public://通过委托创建一个 定时器(Timer) static CTimer*TimerWithDelegate(CTimerDelegate* pDelegate);};#endif // Timer_h__

//Timer.cpp#include "StdAfx.h"#include "Timer.h"////////////////////////////////////////////////////////////////////////////静态成员TIMER_MAPCTimer::m_TimerMap;////////////////////////////////////////////////////////////////////////////构造CTimer::CTimer(CTimerDelegate* pDelegate){m_pDelegate = pDelegate;}void CTimer::TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime){TIMER_MAP::iterator iter = m_TimerMap.find(nTimerid);if (iter != m_TimerMap.end()){CTimer* pTimer = iter->second;pTimer->m_pDelegate->OnTimer(pTimer,pTimer->m_lTimerParam);}}CTimer*CTimer::TimerWithDelegate(CTimerDelegate* pDelegate){CTimer *pTimer = new CTimer(pDelegate);return pTimer;}void CTimer::SetTimer(UINT nElapse,LPVOID lParam/* = NULL*/){UINT nTimerID = ::SetTimer(NULL,m_nTimerID,nElapse,TimerProc);m_lTimerParam = lParam;m_nTimerID  = nTimerID;TIMER_MAP::iterator iter = m_TimerMap.find(m_nTimerID);if (iter == m_TimerMap.end()){//新的定时器,插入到map中 m_TimerMap.insert(TIMER_PAIR(nTimerID,this));}}BOOL CTimer::KillTimer(){BOOL bRet = FALSE;TIMER_MAP::iterator iter = m_TimerMap.find(m_nTimerID);if (iter != m_TimerMap.end()){CTimer* pTimer = iter->second;::KillTimer(NULL,m_nTimerID);m_TimerMap.erase(iter);bRet = TRUE;}delete this;return bRet;}


测试代码:

//main.cpp#include "stdafx.h"#include <cstdio>#include "Timer.h"class CTestTimerDelegate:public CTimerDelegate{private:const char *m_pName;public:CTestTimerDelegate(const char *pName){m_pName = pName;}public:virtual void OnTimer(CTimer *pTimer,LPVOID lParam){int &i = *(int *)lParam;i++;printf("OnTimer(%s):%d\n",m_pName,i);if (i >= 10){pTimer->KillTimer();}}};int main(int argc, char* argv[]){CTestTimerDelegate Obj1("Obj1"),Obj2("Obj2");CTimer *pTimer1 = CTimer::TimerWithDelegate(&Obj1);CTimer *pTimer2 = CTimer::TimerWithDelegate(&Obj2);int     i = 0,j = 0;pTimer1->SetTimer(1000,&i);pTimer2->SetTimer(2000,&j);    //由于是控制台程序,必须实现消息循环,不然timer不工作。MSG   msg;   while(GetMessage(&msg,NULL,0, 0)){   TranslateMessage(&msg);     DispatchMessage(&msg);     }   return 0;}



原创粉丝点击