非窗口类中使用定时器的方法及相关知识的介绍

本文代码运行效果图如下:

摘 要:本文主要通过一些简单的例子,介绍了如何在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(保护的)成员,而全局对象不能。

时间: 2025-01-31 05:12:24

非窗口类中使用定时器的方法及相关知识的介绍的相关文章

VC++实现非窗口类中使用定时器的方法

定时器在Windows 的程序中的作用不可忽略,也随处可见.设定一个时间间隔每0.5秒或者1秒钟刷新一次时钟,这样就可以完成一个简单的电子钟程序.在不同的编程工具中定时器的用法也不同,Visual C++中也给我们提供了实现这种功能的方法,而且方法不只一种.在窗口类中是使用定时器比较很简单,用SetTimer()设置了定时器之后,并在Class Wizard中添加了WM_TIMER消息映射后,您就可以在映射函数OnTimer()中添加代码实现,来定时完成您的任务,而且还支持任意多个定时器,这种方

C#从自定义的窗口类中继承,设计界面无法使用

问题描述 C#从自定义的窗口类中继承,设计界面无法使用 在vs2008中新建一个智能设备项目,创建从Form继承的类 创建继承ChidForm的窗体,打开设计视图后就报错. public partial class Form1 : ChidForm { public Form1() { InitializeComponent(); } } 解决方案 你单步调试,跟踪进去InitializeComponent方法,一步步看看,里面估计有错误 解决方案二: design.cs一定要写好

restlet-在基于spring的REST服务 中如何让每一个资源类中的 每个资源方法都有一个URL呢?

问题描述 在基于spring的REST服务 中如何让每一个资源类中的 每个资源方法都有一个URL呢? 如 在这一篇 博文中 http://my.oschina.net/jiyayun/blog/146446 每一个资源类中都只有一个 方法可用.如果我在一个资源类中有多个 资源方法应该怎么弄呢?求大神帮忙,谢谢了. 解决方案 因为每个类对应一个url如果是每个方法,那么就冲突了.你可以用代码生成器产生代理类,每个类对应一个原始类的方法来解决这个问题.

MFC 按钮添加=BN_CLICKED后 及父窗口类中 不响应按钮点击事件

问题描述 MFC 按钮添加=BN_CLICKED后 及父窗口类中 不响应按钮点击事件 按钮类 添加消息处理 子窗口 =BN_CILCKED void C4PicBtn::OnBnClicked() { MessageBox(L"1"); } 父窗口 ON_BN_CLICKED(IDC_BtnPlay, &CMp3PlayerDlg::OnBnClickedBtnplay) void CMp3PlayerDlg::OnBnClickedBtnplay() { MessageBox

python遍历类中所有成员的方法_python

本文实例讲述了python遍历类中所有成员的方法.分享给大家供大家参考.具体分析如下: 这段代码自定义了一个类,类包含了两个成员title和url,在类的内部定义了一个函数list_all_member用于输出类的所有成员变量及值 # -*- coding: utf-8 -*- class Site(object): def __init__(self): self.title = 'jb51 js code' self.url = 'http://www.jb51.net' def list_

在c# 中 如何在A类中 操作B类中的属性 或方法?

问题描述 有公共类A和公共类B.类A有属性StringName和intAge.类B有方法SetAelement().可否通过B类的方法操作A类中的属性.如果可以,如何实现? 解决方案 解决方案二:classA{StringName;intAge;}classB{SetAelement(){Aa=newA();a.Name="zzy";a.Age=15;}}解决方案三:classB{SetAelement(){A.Name="zzz";A.Age=15;}}解决方案四

ajax调用中ie缓存问题解决方法_AJAX相关

本文实例分析了ajax调用中ie缓存问题解决方法.分享给大家供大家参考,具体如下: ajax请求调用的过程中发现的问题:后台请求是一个简单的.aspx文件,而这个页面又没有考虑过缓存的影响,使用ajax调试的时候发现有时候根本不走后台代码直接返回结果了,所以估计是受到浏览器缓存的影响.网上搜了一下,果然是缓存的问题:"IE中如果XMLHttpRequest提交的URL与历史一样则使用缓存,根本不向服务器端提交.因此无法取到刚提交的数据或新的数据". 解决方法大致有下面几种: 1.只改进

简述JavaScript中正则表达式的使用方法_基础知识

 正则表达式是一个对象,它描述了字符模式. JavaScript的RegExp类表示正则表达式和字符串和正则表达式定义,使用正则表达式来进行强大的模式匹配和搜索和替换文本功能的方法.语法: 正则表达式可以用RegExp( ) 构造这样的定义: var pattern = new RegExp(pattern, attributes); or simply var pattern = /pattern/attributes; 这里是参数的说明:     pattern: 一个字符串,指定正则表达式

详解JavaScript实现设计模式中的适配器模式的方法_基础知识

有的时候在开发过程中,我们会发现,客户端需要的接口和提供的接口发生不兼容的问题.由于特殊的原因我们无法修改客户端接口.在这种情况下,我们需要适配现有接口和不兼容的类,这就要提到适配器模式.通过适配器,我们可以在不用修改旧代码的情况下也能使用它们,这就是适配器的能力. 适配模式可用来在现有接口和不兼容的类之间进行适配,使用这种模式的对象又叫包装器(wrapper),因为它们是在用一个新的接口包装另一个对象. 从表面上看,适配器模式很像外观模式.它们都要对别的对象进行包装并改变其呈现的接口.二者的差