使用SetTimer传递用户数据

GJ.*_*GJ. 15 c++ winapi visual-c++

我在一个类的函数中调用SetTimer.

SetTimer(NULL, 0, 10000, (TIMERPROC) TimerCallBack);  
Run Code Online (Sandbox Code Playgroud)

TimerCallBack的位置是:

static VOID CALLBACK TimerCallBack(HWND, UINT, UINT, DWORD)
Run Code Online (Sandbox Code Playgroud)

现在我需要调用一个启动计时器的类方法,因为TimerCallBack是静态的,它不再能访问类对象.

我无法找到任何方法将对象指针与SetTimer一起传递,以便我可以在回调函数上接收它.

有没有其他方法来实现这一点,如果不支持使用SetTimer,那么我可以实现这一点.

Bru*_*nez 21

你不需要地图.使用idEvent参数.微软给它UINT_PTR类型,所以它适合指针,即使是64位:

SetTimer(hwnd, (UINT_PTR)bar, 1000, MyTimerProc);

void CALLBACK MyTimerProc(HWND, UINT, UINT_PTR idEvent, DWORD)
{
    Bar* bar = (Bar*)idEvent;
}
Run Code Online (Sandbox Code Playgroud)

请注意,您需要使用实际的HWND.如果HWND为null,Windows将在内部生成idEvent.

  • 这应该是评分最高的答案,它是最干净的灵魂 (2认同)

Chr*_*cke 9

显然,如果你在一个窗口指导定时器消息,你可以只用窗口存储用户数据.

使用TimerProc执行此操作的唯一方法是创建一个类,用于管理用户数据对象的定时器ID的静态范围映射.

这样的事情(因为这是一个c ++问题,我只是实现了一个快速和脏的函子类型的东西,以便TimerMgr可以直接安排回调给类的成员,这通常是你试图存储用户数据的原因:

// Timer.h
#include <map>
class CTimer {
public:
  class Callback {
  public:
    virtual void operator()(DWORD dwTime)=0;
  };
  template<class T>
  class ClassCallback : public Callback {
    T* _classPtr;
    typedef void(T::*fnTimer)(DWORD dwTime);
    fnTimer _timerProc;
  public:
    ClassCallback(T* classPtr,fnTimer timerProc):_classPtr(classPtr),_timerProc(timerProc){}
    virtual void operator()(DWORD dwTime){
      (_classPtr->*_timerProc)(dwTime);
    }
  };

  static void AddTimer(Callback* timerObj, DWORD interval){
    UINT_PTR id = SetTimer(NULL,0,interval,TimerProc);
    // add the timer to the map using the id as the key
    _timers[id] = timerObj;
  }
  static void CALLBACK TimerProc(HWND hwnd,UINT msg,UINT_PTR timerId,DWORD dwTime){
    _timers[timerId]->operator()(dwTime);
  }
private:
  static std::map<UINT_PTR, Callback*> _timers;
};

// In Timer.cpp
#include <windows.h>
#include <Timer.h>
std::map<UINT_PTR,CTimer::Callback*> CTimer::_timers;

// In SomeOtherClass.cpp
class CSomeClass {
  void OnTimer1(DWORD dwTime){
  }
public:
  void DoTimerStuff(){
    CTimer::AddTimer( new CTimer::ClassCallback<CSomeClass>(this,&CSomeClass::OnTimer1), 100);
  }
};
Run Code Online (Sandbox Code Playgroud)

从地图中删除计时器留给读者的练习:)


  • ClassCallback需要继承Callback.
  • 需要定义静态变量
  • 代码现在可以在MSVC 9.0上正确构建和运行