头文件内容:
#pragma once typedef function<void ()> DelayClickHandler; 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<DelayData> m_HandlerVec; set<CString> 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<DelayData>::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<m_HandlerVec.size();) { DelayData &dd = m_HandlerVec[i]; DWORD curTime = GetTickCount(); if(curTime >= 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){} }; //调用1 CDelayHandler::PostDelay(A::DoStaticFun,3*1000); //调用2 A a; CDelayHandler::GetInstance()->PostDelay(bind(&A::DoFun,&a,100),3*1000,_T("DoFun"));
注:可能需要其他库