本文代码运行效果图如下:
摘 要:本文主要通过一些简单的例子,介绍了如何在Visual C++的窗口和非窗口类中使用定时器。重点介绍了如何用静态成员函数和静态数据成员在非窗口类中使用定时器,同时,又介绍了与定时器相关的知识,例如回调函数,C++类中的静态成员,以及模板类中的映射类等。
关键字 C++ 类 定时器 静态函数 静态成员函数 静态数据成员 回调函数 映射类
摘 要:This page introduce how to use timer in window class and none window class of Visual C++ by some simple samples. Use timer in none window class with static member variable and static member function is the important point. At the same time, it also tell about of some knowledge such as about timer, callback function, static member of C++ class and map class CMap of template class.
关键字:C++ Class Timer static CALLBACK CMap
一、引言
定时器在Windows 的程序中的作用不可忽略,也随处可见。设定一个时间间隔每0.5秒或者1秒钟刷新一次时钟,这样就可以完成一个简单的电子钟程序。在不同的编程工具中定时器的用法也不同,Visual C++中也给我们提供了实现这种功能的方法,而且方法不只一种。在窗口类中是使用定时器比较很简单,用SetTimer()设置了定时器之后,并在Class Wizard中添加了OnTimer消息映射后,您就可以在映射函数OnTimer()中添加代码实现,来定时完成您的任务,而且还支持任意多个定时器,这种方法大家可能都会用。但是在非窗口的类中,使用定时器就没那么简单了,在类消息映射中就找不到OnTimer()方法了,类中也没有hWnd这个属性,SetTimer()也不能象原来那样使用了,下面给出了一种既不破坏类的完整性的同时又能巧妙的使用定时器的方法。
二、相关知识
在非窗口类中使用定时器,需要了解的知识比较多。首先非窗口类中没有消息映射,也没有象CWnd类具有的SetTimer()方法来设置定时器。没有消息映射,就只能靠我们自己定义的回调函数来处理定时器的消息,因此大家有必要了解一下回调函数的概念。因为回调函数只能用全局函数或者静态成员函数来实现,为了维持类的完整性,使用类的静态成员函数来作为回调函数,所以我们又需要了解一下静态数据成员和静态成员函数的性质。又因为定时器是在我们的程序中产生的,这又需要来管理定时器,所以又用到了映射表类CMap,因此介绍一下CMap的简单用法也是必不可少的。
2.1 回调函数
所谓回调函数就是按照一定的形式由你定义并编写实现内容,当发生某种事件时,而由系统或其它函数来调用的函数。
使用回调函数实际上就是在调用某个函数(通常是API函数)时,将自己编写的一个函数(也就是回调函数)的地址作为参数传递给那个函数。而那个函数在需要的时候,也就是某种事情发生的时候,利用传递的函数地址调用回调函数,这时你可以利用这个机会在回调函数中处理消息或完成一定的操作。回调函数只能是全局函数,或者是静态函数,因为这个函数只是在这个类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。
2.2 C++类中的静态成员
在C语言中,声明一个数据为静态类型,意味着该变量的生存周期是静态的,即在程序的开始时即分配,到程序终止时才释放。但在C++中,声明一个类中的成员为静态类型,则意味着该类的所有实例只有该成员的一个拷贝。也就是说,不管应用程序中创建了这个类的多少个对象,其静态成员只有一个副本,该副本为这个类的所有对象实例所共享,而对于非静态成员,每个类对象实例都有自己的拷贝。例如:
class CPerson
{
public:
CString szName;
static CString szCompanyName;
CPerson();
virtual ~CPerson();
};
接着用该类声明一个实例 CPerson me;
对于同一家公司员工,每个人都有不同的姓名,但是他们的公司名字是一样的,所以就可以用一个静态类型来保存,这样所有的员工都共享这个公司名称,只要一位员工更新了公司名称,则所有员工的公司名称就被更新了。
静态成员被当作该类类型的全局对象,可以把一个静态数据成员和静态成员函数当成全局变量和函数那样去存储和访问,但又被隐藏在类的内部,并且清楚地与这个类相联系但又不是全局对象,同全局对象相比,使用静态成员有两个优势:
(1) 静态成员没有进入程序的全局名字空间,它属于类,它的名字只在类的范围内有效,因此不存在与程序中其他全局名字冲突的可能性。
(2) 可以实现信息隐藏,并可以保持类的完整性,可以是private(私有的)成员、public(公有的)成员或者protected(保护的)成员,而全局对象不能。