头文件内容:
#pragma oncetypedef functionDelayClickHandler;typedef void (*pDelayFun)();class DelayData{public: DelayData(){} //cskey主要是为了避免重复调用,如果cskey空,则不考虑,如果不为空,相同cskey如果之前的没有执行到,会remove之前的,然后加入当前的这个函数 DelayData(pDelayFun pFun,DWORD dwDelayTick,CString csKey="") { dwStartTick = GetTickCount(); this->pFun = pFun; this->dwDelayTick = dwDelayTick; this->csKey = csKey; } DelayData(DelayClickHandler FunHandler,DWORD dwDelayTick,CString csKey="") { dwStartTick = GetTickCount(); this->dwDelayTick = dwDelayTick; this->FunHandler = FunHandler; this->csKey = csKey; pFun = NULL; } DWORD dwStartTick; //记录当时时间 DWORD dwDelayTick; //延迟时间 CString csKey; //表示特征值 pDelayFun pFun; //需要执行的函数,必须是静态函数 DelayClickHandler FunHandler; //需要执行的函数};class CDelayHandler:public CWnd{public: static CDelayHandler* GetInstance(); ~CDelayHandler(void); //只能在主线程执行,现在精度是500ms,pDelayFun需要是类的静态函数或者全局函数,没有参数 static void PostDelay(pDelayFun pFun,DWORD dwDelayTime,CString csKey=""); //只能在主线程执行,现在精度是500ms,FunHandler需要是类的函数,可以带参数,具体可以看CHoverButton中的handler使用方法 void PostDelay(DelayClickHandler FunHandler,DWORD dwDelayTime,CString csKey=""); DECLARE_MESSAGE_MAP()protected: CDelayHandler(void); afx_msg void OnTimer(UINT nIDEvent); void DoDelayHandler(); void AddDelayData(DelayData dd);private: vector m_HandlerVec; set m_HandlerKey; //避免重复加入同一个延迟函数};
cpp文件:
#include "stdafx.h"#include "DelayHandler.h"#define DW_TIMERID 1001//外部接口******************************************************************************************//只能在主线程执行,现在精度是500ms,pDelayFun需要是类的静态函数或者全局函数,没有参数void CDelayHandler::PostDelay(pDelayFun pFun,DWORD dwDelayTime,CString csKey){ CDelayHandler::GetInstance()->AddDelayData(DelayData (pFun,dwDelayTime,csKey));}void CDelayHandler::PostDelay(DelayClickHandler FunHandler,DWORD dwDelayTime,CString csKey){ CDelayHandler::GetInstance()->AddDelayData(DelayData (FunHandler,dwDelayTime,csKey));}//内部实现***************************************************************************************BEGIN_MESSAGE_MAP(CDelayHandler, CWnd) ON_WM_TIMER()END_MESSAGE_MAP()CDelayHandler* CDelayHandler::GetInstance(){ static CDelayHandler _Instance; return &_Instance;}CDelayHandler::CDelayHandler(void){}CDelayHandler::~CDelayHandler(void){}void CDelayHandler::AddDelayData(DelayData dd){ if(NULL == GetSafeHwnd()) { HCURSOR hCursor = AfxGetApp()->LoadCursor(IDC_ARROW); LPCTSTR className = AfxRegisterWndClass(CS_DBLCLKS, hCursor); CreateEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW, className, NULL, WS_POPUP, 0, 0, 0, 0, ::GetDesktopWindow(), NULL); ShowWindow(SW_HIDE); } if(0 == m_HandlerVec.size()) SetTimer(DW_TIMERID,500,NULL); if(dd.csKey.IsEmpty()) { m_HandlerVec.push_back(dd); } else if(m_HandlerKey.find(dd.csKey)==m_HandlerKey.end()) { m_HandlerKey.insert(dd.csKey); m_HandlerVec.push_back(dd); } else if(m_HandlerKey.find(dd.csKey)!=m_HandlerKey.end()) { vector::iterator it = m_HandlerVec.begin(); for(;it!=m_HandlerVec.end();it++) { if(dd.csKey == (it->csKey)) { m_HandlerVec.erase(it); break; } } m_HandlerVec.push_back(dd); }}void CDelayHandler::OnTimer(UINT nIDEvent){ if(nIDEvent == DW_TIMERID) { DoDelayHandler(); if(0==m_HandlerVec.size()) { KillTimer(DW_TIMERID); } } CWnd::OnTimer(nIDEvent);}void CDelayHandler::DoDelayHandler(){ for(int i=0;i = dd.dwStartTick+dd.dwDelayTick) { if(dd.pFun) dd.pFun(); else dd.FunHandler(); if(!dd.csKey.IsEmpty() && m_HandlerKey.find(dd.csKey)!=m_HandlerKey.end()) { m_HandlerKey.erase(m_HandlerKey.find(dd.csKey)); } m_HandlerVec.erase(m_HandlerVec.begin()+i); continue; } ++i; }}
具体使用:
class A{ static void DoStaticFun(){} void DoFun(int n){}};//调用1CDelayHandler::PostDelay(A::DoStaticFun,3*1000);//调用2A a;CDelayHandler::GetInstance()->PostDelay(bind(&A::DoFun,&a,100),3*1000,_T("DoFun"));
注:可能需要其他库