登录站点

用户名

密码

在非窗口类中使用定时器

已有 423 次阅读  2010-08-31 11:05   标签定时器  窗口 
在非窗口类中使用定时器

  在非窗口类中使用定时器就要用到前面我们介绍到的所有知识了。因为是无窗口类,所以我们不能使用在窗口类中用消息映射的方法来设置定时器,这时候就必须要用到回调函数。又因为回调函数是具有一定格式的,它的参数不能由我们自己来决定,所以我们没办法利用参数将this传递进去。可是静态成员函数是可以访问静态成员变量的,因此我们可以把this保存在一个静态成员变量中,在静态成员函数中就可以使用该指针,对于只有一个实例的指针,这种方法还是行的通的,由于在一个类中该静态成员变量只有一个拷贝,对于有多个实例的类,我们就不能用区分了。解决的办法就是把定时器标志值作为关键字,类实例的指针作为项,保存在一个静态映射表中,因为是标志值是唯一的,用它就可以快速检索出映射表中对应的该实例的指针,因为是静态的,所以回调函数是可以访问他们的。

  首先介绍一下用于设置定时的函数:

UINT SetTimer(
  HWND hWnd,       // handle of window for timer messages
  UINT nIDEvent,     // timer identifier
  UINT uElapse,      // time-out value
  TIMERPROC lpTimerFunc  // address of timer procedure
  );

  其中的参数意义如下:

  hWnd: 指定与定时器相关联的窗口的句柄。这里我们设为NULL。

  nIDEvent: 定时器标志值,如果hWnd参数为NULL,它将会被跳过,所以我们也设定为NULL。

  uElapse: 指定发送消息的时间间隔,单位是毫秒。这里我们不指定,用参数传入。

  lpTimerFunc: 指定当间隔时间到的时候被统治的函数的地址,也就是这里的回调函数。这个函数的格式必须为以下格式:

VOID CALLBACK TimerProc(
  HWND hwnd,   // handle of window for timer messages
  UINT uMsg,   // WM_TIMER message
  UINT idEvent, // timer identifier
  DWORD dwTime  // current system time
);

  其中的参数意义如下:

  hwnd: 与定时器相关联的窗口的句柄。

  uMsg: WM_TIMER消息。

  idEvent: 定时器标志值。

  deTime: 系统启动后所以经过的时间,单位毫秒。

  最后设定定时器的代码为:

m_nTimerID = SetTimer(NULL,NULL,nElapse,MyTimerProc);

  先通过Class Wizard创建一个非窗口类,选择Generic Class类类型,类名称为CMyTimer,该类的作用是每隔一段时间提醒我们做某件事情,然后用这个类创建三个实例,每个实例以不同的时间间隔提醒我们做不同的事情。

  MyTimer.h

#include <afxtempl.h>
class CMyTimer;
//用模板类中的映射表类定义一种数据类型
typedef CMap<UINT,UINT,CMyTimer*,CMyTimer*> CTimerMap;
class CMyTimer 
{
public:
  //设置定时器,nElapse表示时间间隔,sz表示要提示的内容
  void SetMyTimer(UINT nElapse,CString sz);
  //销毁该实例的定时器
  void KillMyTimer();
  //保存该实例的定时器标志值
  UINT m_nTimerID;
  //静态数据成员要提示的内容
  CString szContent;
  //声明静态数据成员,映射表类,用于保存所有的定时器信息
  static CTimerMap m_sTimeMap;
  //静态成员函数,用于处理定时器的消息
  static void CALLBACK MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime);
  CMyTimer();
  virtual ~CMyTimer();
};

  MyTimer.cpp

 

#include "stdafx.h"
#include "MyTimer.h"
//必须要在外部定义一下静态数据成员
CTimerMap CMyTimer::m_sTimeMap;
CMyTimer::CMyTimer()
{
  m_nTimerID = 0;
}
CMyTimer::~CMyTimer()
{
}
void CALLBACK CMyTimer::MyTimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
  CString sz;
  sz.Format("%d号定时器:%s",
    idEvent,
    m_sTimeMap[idEvent]->szContent);
  AfxMessageBox(sz);
}
void CMyTimer::SetMyTimer(UINT nElapse,CString sz)
{
  szContent = sz;
  m_nTimerID = SetTimer(NULL,NULL,nElapse,MyTimerProc);
  m_sTimeMap[m_nTimerID] = this;
}
void CMyTimer::KillMyTimer()
{
  KillTimer(NULL,m_nTimerID);
  m_sTimeMap.RemoveKey(m_nTimerID);
}

  这样就完成了在非窗口类中使用定时器的方法。以上这些代码都在Windwos 2000 Professional 和 Visual C++ 6.0中编译通过。

  五、结论

  通过以上的介绍,大家应该知道如何在静态成员函数中访问非静态数据成员和非静态成员函数,并了解了如何在非窗口类中使用定时器。当然这只是解决这个问题的一种方法,相信还有更好的解决办法。这个种方法有一定的灵活性,可以在很多地方用到,例如网络程序中的连接超时以及定时刷新等需要自己来控制,就可以使用这种方法。

  参考文献:

  1 潘爱民 张丽.C++ Primer 中文版.(第三版).北京:中国电力出版社.2002

  2 Jeff Prosise.MFC Windows 程序设计.(第二版).北京:清华大学出版社.2001

  3 王险峰,刘宝宏.Windows环境下的多线程编程原理与应用.北京:清华大学出版社.2002

  4 侯俊杰.深入浅出MFC.台湾:松岗电脑图资料股份有限公司.1998

上一篇: 用skinmagic给VC6开发的软件换肤 下一篇: VC++对话框程序打印及打印预览的实现方法

分享 举报