VC++    WM_TIMER   定时器使用方法
      在编程时,会经常使用到定时器。使用定时器的方法比较简单,通常告诉Windows一个时间间隔,然后WINDOWS以此时间间隔周期性触发程序。通常有两种方法来实现:发送WM_TIMER消息和调用应用程序定义的回调函数。
 
1.1 用WM_TIMER来设置定时器
 
先请看SetTimer这个API函数的原型
 
UINT_PTR SetTimer(
HWND hWnd, // 窗口句柄
UINT_PTR nIDEvent, // 定时器ID,多个定时器时,可以通过该ID判断是哪个定时器
UINT uElapse, // 时间间隔,单位为毫秒
TIMERPROC lpTimerFunc // 回调函数
);

  

 
例如 :
SetTimer(m_hWnd,1,1000,NULL); //一个1秒触发一次的定时器
在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了,例如:
UINT SetTimer(1,100,NULL);
函数反回值就是第一个参数值1,表示此定时器的ID号。
 
第二个参数表示要等待100毫秒时间再重新处理一次。第三个参数在这种方法中一般用NULL。
注意:设置第二个参数时要注意,如果设置的等待时间比处理时间短,程序就会出问题了。
 
1.2 调用回调函数
 
此方法首先写一个如下格式的回调函数
 
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);
然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回调函数地址。
 
二、多个定时器的实现与应用
 
我们在安装定时器时都为其指定了ID,使用多个定时器时,该ID就发挥作用了。
不使用MFC时,当接收到WM_TIMER消息,WPARAM wParam中的值便是该定时器的ID
使用MFC时就更简单了,我们为其增加WM_TIME的消息处理函数OnTimer即可,请看如下例子 
void CTimerTestDlg::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 24: ///处理ID为24的定时器
Draw1();
break;
case 25: ///处理ID为25的定时器
Draw2();
break;
}
CDialog::OnTimer(nIDEvent);
}

  

当你用回调函数时,我们可以根据nTimerid的值来判断是哪个定时器,例如:
void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime)
{
switch(nTimerid)
{
case 1: ///处理ID为1的定时器
Do1();
break;
case 2: ///处理ID为2的定时器
Do2();
break;
}
}

  

三、取消定时器
 
不再使用定时器后,我们应该调用KillTimer来取消定时,KillTimer的原型如下
 
BOOL KillTimer(
HWND hWnd, // 窗口句柄
UINT_PTR uIDEvent // ID
);
在MFC程序中我们可以直接调用KillTimer(int nIDEvent)来取消定时器。
 

如:KillTimer(1);

——————————————————————————————————————————————————

MFC中定时器的使用

 

巧妙地使用定时器能达到意想不到的效果,写界面的时候能实现渐变,也能帮助多线程控制等
我们知道,在VC的MFC中,已经为我们封装好了很多全面和强大的函数集,所以在MFC编程时,巧妙地调用MFC函数库可以为我们省去很多麻烦。其中定时器也可以在MFC程序中很好地利用。

在MFC中和定时器相关的有三个函数:
1.设置定时器(定义一个定时器的属性):
SetTimer( UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD));

2.定时器响应(响应系统定义WM_TIMER消息):
OnTimer( UINT nIDEvent );

3.释放定时器:
KillTimer( int nIDEvent );

其中:
UINT nIDEvent:定时器的ID,在一个程序中用这个ID来确定是那个定时器发送的消息。
UINT nElapse: 定义刷新时间,即间隔多长时间刷新一次,单位是毫秒。
void (CALLBACK EXPORT* lpfnTimer)( HWND, UINT, UINT, DWORD):回调函数的参数,实现刷新时所做的操作,一般情况下都设为0。

demo1

在这里就用一个简单的例子来说明定时器在MFC中是如何使用的。
1.建立单文档程序Timer。

2.在resource.h中定义两个定时器的ID
#define TIMER1 1
#define TIMER2 2

3.在CMainFrame的OnCreate函数中定义两个定时器的属性。
SetTimer(TIMER1,3000,0);
SetTimer(TIMER2,5000,0);

4.在类视图中右击CMainFrame属性,在消息响应函数中找到WM_TIMER,然后添加响应函数OnTimer()。

void CMainFrame::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
switch(nIDEvent)
{
case TIMER1:
{
AfxMessageBox("定时器1!");
break;
}
case TIMER2:
{
AfxMessageBox("定时器2!");
break;
}
default:
break;
}
CFrameWnd::OnTimer(nIDEvent);
}

  

5.在CMainFrame的析构函数中添加释放定时器函数。
KillTimer(TIMER1);
KillTimer(TIMER2);

这样,一个简单的定时器程序就生成了,运行后可以看到,每隔3秒就会弹出一个消息对话框“定时器1”,每隔5秒就会弹出一个消息对话框“定时器2”。

这种情况是在程序运行后定时器就直接启动了,很多时候我们需要的是在响应一次事件或者说点击一个按钮后再去执行定时器,那么这时应该怎么修改呢?也用一个实例来说明吧,因为我觉得可能说一大堆废话也抵不上一个简单而正确的实例更具说服力。

demo2

现在,我生成了一个MFC多文档应用程序,我希望在点击菜单条上的某个按钮后再去执行定时器。这时就不是在CMainFrame里面操作了,因为我们是要在对话框上进行定时器的操作,而CView这个类是负责对话框的对应操作,所以要把定时器定义在CView里面。
1.建立多文档程序Timer。

2.在resource.h中定义两个定时器的ID
#define TIMER1 1
#define TIMER2 2

3.在CTimerView的OnInitialUpdate函数中定义两个定时器的属性
SetTimer(TIMER1,3000,0);
SetTimer(TIMER2,5000,0);

4.在类视图中右击CTimerView属性,在消息响应函数中找到WM_TIMER,然后添加响应函数OnTimer()。

void CTimerView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
//Hwnd为一个变量,初始值为false,点击某个按钮后在其响应函数中将其置为true
switch(nIDEvent && Hwnd){
case TIMER1:
{
AfxMessageBox("定时器1!");
break;
}
case TIMER2:
{
AfxMessageBox("定时器2!");
break;
}
default:
break;
}
CFrameWnd::OnTimer(nIDEvent);
}

  

5.在CTimerView中添加OnDestroy()函数,在函数中释放定时器。
KillTimer(TIMER1);
KillTimer(TIMER2);

现在,运行程序后,没有马上弹出预定的对话框,而是在我们点击某个按钮或者响应某个事件后对话框才弹出,同样是点击按钮后,每隔3秒弹出对话框“定时器1”,每隔5秒弹出“定时器2”。
其实在不同的类,定时器的用法都是基本一致的,只要找到类的初始函数和释放函数,就能轻松实现定时功能了,就这么简单。

demo3

基于对话框的定时器程序

1.打开VC,新建一基于对话框的工程,工程名为Test在对话框上添加一按钮,将其ID改为IDC_BUTTON_START,Caption改为Start. 映像该按钮的BN_CLICKED消息,void CTestDlg::OnButtonStart();

2.再在对话框上添加一按钮,ID为ID_BUTTON_STOP,Caption改为Stop,映像消息为void CTestDlg::OnButtonStop();

3.添加一个Lable,ID改为IDC_STATIC_TIME,用于记数,表明定时器函数的执行。

4.映像对话框的WM_TIMER消息,void CTestDlg::OnTimer(UINT nIDEvent);

以上的实现函数如下所示:

void CTestDlg::OnButtonStart()

{

SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒

}

void CTestDlg::OnButtonStop()

{

KillTimer(1);//关闭定时器1。

}

void CTestDlg::OnTimer(UINT nIDEvent)

{

static int nTimer=0;

CString strTmp="";

strTmp.Format("Timer:%d",nTimer++);

CWnd *pWnd=GetDlgItem(IDC_STATIC_TIME);

pWnd->SetWindowText(strTmp); //在Lable中设置新值,表明定时器已经工作。

CDialog::OnTimer(nIDEvent);

}

  

回调函数的使用。

如果不想使用窗体的WM_TIMER消息函数处理,可以使用回调函数来取代,读者可以在上面例子的基础上,增加一个回调函数,以证实前面的讨论。

首先,定义一个回调函数,回调函数的定义必须按照如下格式。必须值静态的

void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime );

我的实现函数如下:

void CALLBACK TimerProc(HWND hwnd,UINT uMsg,UINT idEvent,DWORD dwTime )

{

AfxMessageBox("Timer is running!");//定时器时间到,强出一对话框,表明定时器已经运行。

}

  

将上面的启动函数稍做修改

void CTestDlg::OnButtonStart()

{

//SetTimer(1,1000,NULL);//启动定时器1,定时时间是1秒

SetTimer(1,1000,(TIMERPROC)TimerProc);//用回调函数处理,此时对话框的消息处理函数不再处理。

}

  

转载自:http://my.oschina.net/ypimgt/blog/61061

程序员的基础教程:菜鸟程序员

VC++ 定时器使用总结的更多相关文章

  1. Win10系列:VC++ 定时器

    计时器机制俗称"心跳",表示以特定的频率持续触发特定事件和执行特定程序的机制.在开发Windows应用商店应用的过程中,可以使用定义在Windows::UI::Xaml命名空间中的 ...

  2. VC++ 6.0使用定时器SetTimer;

    背景: windows中使用VC++6.0制作了个交互界面向下位机定时发送数据及显示下位机上传的数据.定时发送则需要使用定时器. 本文只做记录如何调用,原理以后再深究. 正文: 首先,我生成的窗体类名 ...

  3. VC++或QT下 高精度 多媒体定时器

    在VC编程中,用SetTimer可以定义一个定时器,到时间了,就响应OnTimer消息,但这种定时器精度太低了.如果需要精度更高一些的定时器(精 确到1ms),可以使用下面的高精度多媒体定时器进行代码 ...

  4. Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用

    OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...

  5. VC中基于 Windows 的精确定时[转]

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  6. Qt与VC编程合作起龌龊

    由于历史原因,某软件项目的界面采用QT,而后台用了VC,界面静态调用了VC生成的dll,一直以来都能够快乐的合作,然而最近出现两个小问题,觉得两者之间的合作并没有想象的那么美好. 在VC下用多媒体定时 ...

  7. 《VC++ 6简明教程》即VC++ 6.0入门精讲 学习进度及笔记

    VC++6.0入门→精讲 2013.06.09,目前,每一章的“自测题”和“小结”三个板块还没有看(备注:第一章的“实验”已经看完). 2013.06.16 第三章的“实验”.“自测题”.“小结”和“ ...

  8. VC杂记

    获得Combobox的状态:向ComboBox发送CB_GETDROPPEDSTATE消息. 格式化字串:char buff[10] ; sprintf(buff,"1+1=%d" ...

  9. VC++大数据量绘图时无闪烁刷屏技术实现(我的理解是,在内存上作画,然后手动显示,而不再直接需要经过WM_PAINT来处理了)

    http://hantayi.blog.51cto.com/1100843/383578 引言 当我们需要在用户区显示一些图形时,先把图形在客户区画上,虽然已经画好但此时我们还无法看到,还要通过 程序 ...

随机推荐

  1. Windows Event 事件

    事件对象就像一个开关:它只有两种状态(开和关). 开状态:我们称其为“有信号” 关状态:我们称其为“无信号” 可以在一个线程的执行函数中创建一个事件对象,然后观察它的状态,如果是“无信号”就让该线程睡 ...

  2. TensorFlow相关的一些技巧

    谷歌开发技术推广工程师 Laurence Moroney 在 Google Cloud Next 大会上进行了一段 42 分钟的演讲,主题是「What's New with TensorFlow?」. ...

  3. jenkins将构建成功或失败的信息发送给指定URL(eg: pomelo采用jenkins持续集成)

     先提供一个思路供大家参考,想将构建成功或者失败的信息发送给指定URL的话,可以这样:1.A构建后触发另一个构建B,构建B执行某个插件2.插件的功能:   (1)利用jenkins API获取构建A最 ...

  4. 2017-2018-2 20165233 实验三 敏捷开发与XP实践

    20165233 实验三 敏捷开发与XP实践 实验内容 XP基础 XP核心实践 相关工具 实验步骤 一.编码标准 编程标准包含:具有说明性的名字.清晰的表达式.直截了当的控制流.可读的代码和注释,以及 ...

  5. 0_Simple__template

    简单的 CUDA 应用模板,白送的 Sample. ▶ 源代码 //template_cpu.cpp extern "C" void computeGold(float *, co ...

  6. leetcode485

    public class Solution { public int FindMaxConsecutiveOnes(int[] nums) { ; ; ; i < nums.Length; i+ ...

  7. 万字总结:学习MySQL优化原理,这一篇就够了!

    前言 说起MySQL的查询优化,相信大家收藏了一堆奇技淫巧:不能使用SELECT *.不使用NULL字段.合理创建索引.为字段选择合适的数据类型..... 你是否真的理解这些优化技巧?是否理解其背后的 ...

  8. 切换svn登录账户

    右键-->TortoiseSVN-->设置 找到:点击已缓存数据 在认证数据一栏点击:清空

  9. 程序员教程-9章-C程序设计

    目录结构: 9.1 C语言基础 9.1.1 数据类型 1 基本数据类型 2 数组.字符数组与字符串 3 枚举类型 4 结构体.共用体和typedef 9.1.2 运算符与表达式 9.1.3 输入/输出 ...

  10. kernel TCP time wait bucket table overflow

    # 故障描述 有一个需求是实时分析API接口访问日志,提取token去数据库查询对应的uid,然后收集一些指标存入到hbase中. 当程序执行一会后会被系统杀死 Killed ! # 故障排查 .CP ...