实现PC延迟执行函数

头文件内容:

#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"));

注:可能需要其他库

原文地址:https://www.cnblogs.com/jlyg/p/10006145.html