• 实现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"));

    注:可能需要其他库

  • 相关阅读:
    解决 minwidth 在 IE6 中无效的方法
    SmallSlider 图片轮播插件
    css li中a的高端与li的高端不一致,解决方案
    为什么height:5px在IE6里显示不正常?
    命令提示符下不能输入中文
    Sql中日期差 Sql中 DateDiff Sql 中时间差
    20100420 18:17 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters
    多个表结果的并列显示
    linux系统下载地址
    VMware中Shared Folders(共享文件夹)的配置
  • 原文地址:https://www.cnblogs.com/jlyg/p/10006145.html
Copyright © 2020-2023  润新知