SetTimer
目录
1、SetTimer函数的用法
1)用WM_TIMER来设置定时器
先请看SetTimer这个API函数的原型
UINT_PTRSetTimer(
HWNDhWnd,//窗口句柄
UINT_PTRnIDEvent,//定时器ID,多个定时器时,可以通过该ID判断是哪个
定时器
UINTuElap,//时间间隔,单位为毫秒
TIMERPROClpTimerFunc//回调函数
);
例如
SetTimer(m_hWnd,1,1000,NULL);//一个1秒触发一次的定时器
在MFC程序中SetTimer被封装在CWnd类中,调用就不用指定窗口句柄了
于是SetTimer函数的原型变为:
UINTSetTimer(UINTnIDEvent,UINTnElap,void(CALLBACKEXPORT
*lpfnTimer)(HWND,UINT,UINT,DWORD))
当使用SetTimer函数的时候,就会生成一个计时器。函数中nIDEvent指的是
计时器的标识,也就是名字。nElap指的是时间间隔,也就是每隔多长时间触发一
次事件。第四个参数是一个回调函数,在这个函数里,放入你想要做的事情的代码,
你可以将它设定为NULL,也就是使用系统默认的回调函数,系统默认回调的是onTime
函数。
这个函数怎么生成的呢?
你需要在计时器的类中生成onTime函数:在ClassWizard里,选择需要计时
器的类,添加WM_TIME消息映射,就自动生成onTime函数了。然后在函数里添加代
码,让代码实现功能。
每隔一段时间就会自动执行一次。
SetTimer计时器是系统资源,使用完毕应及时用KillTimer销毁,关于SetTimer
的返回值:如果hWnd为NULL,返回值为新建立的timer的ID,如果hWnd非NULL,
返回一个非0整数,如果SetTimer调用失败则返回0,简言之,SetTimer的返回值
用于将来的销毁。
改变计时器的时间间隔
如果想将一个已经存在的计时器设定为不同的时间间隔,可以简单地用不同的时
间值再次调用SetTimer。
计时器精确吗?
计时器并不精确。有两个原因:
原因一:Windows计时器是硬件和ROM
BIOS架构下之计时器一种相对简单的扩充。回到Windows以前的MS-DOS程序写
作环境下,应用程式能够通过拦截者称为timertick的BIOS中断来实现时钟或计时
器。一些为MS-DOS编写的程序自己拦截这个硬件中断以实现时钟和计时器。这些中
断每54.915毫秒产生一次,或者大约每秒18.2次。这是原始的IBMPC的微处理器
频率值4.772720MHz被218所除而得出的结果。在Windows98中,计时器与其下的
PC计时器一样具有55毫秒的解析度。在MicrosoftWindowsNT中,计时器的解析度
为10毫秒。Windows应用程式不能以高于这些解析度的频率(在Windows98下,每
秒18.2次,在WindowsNT下,每秒大约100次)接收WM_TIMER消息。在SetTimer
中指定的时间间隔总是截尾后tick数的整数倍。例如,1000毫秒的间隔除以54.925
毫秒,得到18.207个tick,截尾后是18个tick,它实际上是989毫秒。对每个小
于55毫秒的间隔,每个tick都会产生一个WM_TIMER消息。可见,计时器并不能严
格按照指定的时间间隔发送WM_TIMER消息,它总要相差那么几毫秒。即使忽略这几
个毫秒的差别,计时器仍然不精确。请看原因二:
WM_TIMER消息放在正常的消息队列之中,和其他消息排列在一起,因此,如果在
SetTimer中指定间隔为1000毫秒,那么不能保证程序每1000毫秒或者989毫秒就会
收到一个WM_TIMER消息。如果其他程序的执行事件超过一秒,在此期间内,您的程
式将收不到任何WM_TIMER讯息。事实上,Windows对WM_TIMER消息的处理非常类
似于对WM_PAINT消息的处理,这两个消息都是低优先级的,程序只有在消息队列中
没有其他消息时才接收它们。WM_TIMER还在另一方面和WM_PAINT相似:Windows不
能持续向消息队列中放入多个WM_TIMER讯息,而是将多余的WM_TIMER消息组合成一
个消息。因此,应用程序不会一次收到多个这样的消息,尽管可能在短时间内得到两
个WM_TIMER消息。应用程序不能确定这种处理方式所导致的WM_TIMER消息「遗漏」
的数目。可见,WM_TIMER消息并不能及时被应用程序所处理,WM_TIMER在消息队列
中的延误可能就不能用毫秒来计算了。
由以上两点,你不能通过在处理WM_TIMER时一秒一秒计数的方法来计时。如果
要实现一个时钟程序,可以使用系统的时间函数如GetLocalTime,而在时钟程序中,
计时器的作用是定时调用GetLocalTime获得新的时间并刷新时钟画面,当然这个刷
新的间隔要等于或小于1秒。
2、例:
1)不用回调函数
SetTimer(1,1000,NULL);
1:计时器的名称;
1000:时间间隔,单位是毫秒;
NULL:使用onTime函数。
当不需要计时器的时候调用KillTimer(nIDEvent);
例如:KillTimer(1);
2)调用回调函数
此方法首先写一个如下格式的回调函数
voidCALLBACKTimerProc(HWNDhWnd,UINTnMsg,UINTnTimerid,DWORDdwTime);
然后再用SetTimer(1,100,TimerProc)函数来建一个定时器,第三个参数就是回
调函数地址。
或许你会问,如果我要加入两个或者两个以上的timer怎么办?
继续用SetTimer函数吧,上次的timer的ID是1,这次可以是2,3,4。。。。
SetTimer(2,1000,NULL);
SetTimer(3,500,NULL);
嗯,WINDOWS会协调他们的。当然onTimer函数体也要发生变化,要在函数体内
添加每一个timer的处理代码:
onTimer(nIDEvent)
{
switch(nIDEvent)
{
ca1:........;
break;
ca2:.......;
break;
ca3:......;
break;
}
}
//串口助手保存数据程序
voidCSCOMMDlg::OnButtonSavedata()
{
//TODO:Addyourcontrolnotificationhandlercodehere
UpdateData(TRUE);
intnLength;
nLength=m_gth();
for(intnCount=0;nCount
{
if(m_(nCount)=='')
CreateDirectory(m_(nCount+1),NULL);
}
CreateDirectory(m_strCurPath,NULL);
CFilem_rFile;
LPCSTRlpszPath=m_strCurPath;//"c:comdata";
SetCurrentDirectory(lpszPath);
//文件名为Rec**.txt,以下代码自动检测文件名是否存在,若存在,则后面
序号自动递增
//如,程序自动为正要保存的文件命名为.
charbuf[20];
for(intj=0;j<100;j++)
{
sprintf(buf,"Rec%",j);
if((access(buf,0))==-1)
break;
}
if(!m_(buf,CFile::modeCreate|CFile::modeWrite))
{
AfxMessageBox("创建记录文件失败!");
return;
}
if((access(buf,0))==-1)
{
AfxMessageBox("failed");
return;
}
CTimet=CTime::GetCurrentTime();
CStringstr=("%Y年%m月%d日%H时%M分%S秒rn");
m_((LPCTSTR)str,gth());
m_((LPCTSTR)m_ReceiveData,m_gth());
m_();
m_();
str="OK,";
for(inti=0;i<5;i++)
str+=buf[i];
str+=".txtsaved";
m_dowText(str);
SetTimer(2,5000,NULL);//在定时器中显示保存文件状态
}
//串口助手定时器函数
voidCSCOMMDlg::OnTimer(UINTnIDEvent)
{
//TODO:Addyourmessagehandlercodehereand/orcalldefault
CStringstrStatus;
switch(nIDEvent)
{
ca1:OnButtonManualnd();
break;
ca2:m_dowText(m_strCurPath);
KillTimer(2);
break;
ca3:
m_Window(TRUE);
m_Window(TRUE);
m_Window(TRUE);
m_strSendFilePathName=m_strTempSendFilePathName;
m_dowText(m_strSendFilePathName);//m_strSendFi
lePathName
KillTimer(3);
if(!(m_ck()))
{
if(m_rt(this,m_nCom,
m_nBaud,m_cParity,m_nDatabits,m_nStopbits,m_dwCommEvents,512))
{
m_onitoring();
("STATUS:COM%d
OPENED,%d,%c,%d,%d",m_nCom,m_nBaud,m_cParity,m_nDatabits,m_nStopbits);
m_n(m_hIconRed);
}
el
{
AfxMessageBox("Failedtoretndbuffersize!");
m_n(m_hIconOff);
}
m_dowText(strStatus);
}
break;
ca4:m_xtImage();
break;
default:break;
}
CDialog::OnTimer(nIDEvent);
}
本文发布于:2022-11-23 19:17:24,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/7595.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |