请大家来研究一下高精度定时器函数的用法.(100分)

  • 主题发起人 主题发起人 hejiesi
  • 开始时间 开始时间
H

hejiesi

Unregistered / Unconfirmed
GUEST, unregistred user!
有下面的一些语句<br><br>var<br>&nbsp; uTimerRes,uTimerID:UNIT;<br><br>............<br><br>procedure Tform1.Button1Click(Sender:Tobject);<br>begin<br>&nbsp; uTimerRes:=10; &nbsp;<br>&nbsp; timeBeginPeriod(uTimerRes);<br>&nbsp; uTimerID:=timeSetEvent(uTimerRes, uTimerRes, @timecallback, 0 ,TIME_PERIOD);<br>&nbsp; if uTimerID=0 then timeEndPeriod(uTimerID);<br>end;<br><br>procedure Tform1.timecallback(uTimerID,uMessage : UINT; dwUser, dw1, dw2 : Dword);<br>begin<br>&nbsp; &nbsp;.......<br>end;<br><br>但出现Variable required 的错误, 光标停在timeSetEvent 中@timecallback 的逗号后面, Why?
 
hehehehe, TimeCallBack不能定义为类函数, 必须定义成静态函数.
 
GetTickCount可以得到精度高一些的定时器(ms级别精度),<br>另外直接读系统I/O也可以得到ns级别的精度。
 
这个问题好像urus兄研究得比较透彻,他还有个能精确到0.01ms的控件。<br>建议去看看。
 
............<br><br>var<br>&nbsp; Form1: TForm1;<br>&nbsp; i:integer=0; <br>&nbsp; TIMER_RES:UINT=10;<br>&nbsp; uTimerRes,uTimerID:UINT;<br><br>implementation<br><br>{$R *.DFM}<br><br>procedure CallBack(uTimerID,uMessage:UINT; dwUser,dw1,dw2:Dword);<br>begin<br>&nbsp; if i&gt;10000 then exit;<br>&nbsp; inc(i);<br>&nbsp; form1.label1.caption:=inttostr(i);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>var<br>&nbsp; tc : TIMECAPS;<br>begin<br>&nbsp; timeGetDevCaps (@tc, sizeof (TIMECAPS)) ;<br>&nbsp; uTimerRes:=max(tc.wPeriodMin, TIMER_RES);<br>&nbsp; uTimerRes:=min(uTimerRes,tc.wPeriodMax);<br>&nbsp; timeBeginPeriod (uTimerRes) ;<br>&nbsp; uTimerID:=timeSetEvent(max(uTimerRes,100),uTimerRes, @CallBack, 0, TIME_ONESHOT) ;<br>&nbsp; if (uTimerID = 0) then timeEndPeriod (uTimerRes) ;<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br>&nbsp; if uTimerID&lt;&gt;0 then<br>&nbsp; &nbsp; timeKillEvent(uTimerID) ;<br>&nbsp; timeEndPeriod(uTimerRes) ;<br>end;<br><br>end.<br>为什么上面的代码能通过编译但一点击Button1的时候就会发生错误连CPU调试窗口也出来了.
 
To &nbsp;steve:<br>&nbsp; 到哪里看,请指明.
 
  以下是一个完整的多媒体定时器设计示例程序,该定时器的精度为1毫秒。<br>程序清单如下:<br>#include &lt; vcl.h &gt;<br>#pragma hdrstop<br>#include "mmsystem.h" //包含多媒体定时器函数的头文件<br>#define MilliSecond 1 //定时间隔1毫秒<br>#define Accuracy 1 //系统允许的分辨率最小值<br>#define Min(x,y) ((x &lt; y) ? x : y)<br>#define Max(x,y) ((x &gt; y) ? x : y)<br>#include "HighTimerU.h"<br>//------------------------------------------------<br>#pragma package(smart_init)<br>#pragma resource "*.dfm"<br>UINT TimerID; //定义定时器句柄<br>int count; //定义一个变量以进行计数<br>int TimerAccuracy;<br>TForm1 *Form1;<br>//------------------------------------------------<br>__fastcall TForm1::TForm1(TComponent* Owner)<br>: TForm(Owner)<br>{<br>}<br>void PASCAL TimerCallProc(UINT TimerID, UINT msg,DWORD dwUser,DWORD dwa,DWORD dwb) <br>//定义定时器事件的调用函数<br>{<br>count++;<br>Form1- &gt;Edit1-&gt;Text=count; <br>//在一个编辑框内显示计数值,即定时值<br>}<br><br>//---------------------------------------------------<br>void __fastcall TForm1::Button1Click(TObject *Sender)<br>{<br>TIMECAPS timecaps;<br>int TimerResolution;<br><br>//从系统获得关于定时器服务能力的信息,<br>//分辨率不能超出系统许可值(1到16毫秒)<br>if (timeGetDevCaps(&amp;timecaps,sizeof(<br>&nbsp; &nbsp; TIMECAPS))==TIMERR_NOERROR)<br>TimerAccuracy=Min(Max(timecaps.wPeriodMin,<br>&nbsp; &nbsp; Accuracy),timecaps.wPeriodMax);<br><br>timeBeginPeriod(TimerAccuracy); <br>//设置定时器分辨率<br><br>TimerResolution=1; //设置定时间隔为1毫秒<br><br>//产生间隔1毫秒,周期执行的定时器事件;启动定时器<br>TimerID = timeSetEvent(TimerResolution,TimerAccuracy,<br>&amp;TimerCallProc,1,TIME_PERIODIC);<br>}<br>//-------------------------------------------------------<br>void __fastcall TForm1::Button2Click(TObject *Sender)<br>{<br>timeKillEvent(TimerID); //删除定时器事件<br>timeEndPeriod(TimerAccuracy); //清除定时器分辨率<br>}<br>  多媒体定时器对实现高精度定时是很理想的工具,而且其精度是十分可靠的。<br>但是,因为它可靠的精度是建立在对系统资源的消耗之上的。因此必须注意以下几点:<br>1. 多媒体定时器的设置分辨率不能超出系统许可范围。<br>2. 在使用完定时器以后,一定要及时删除定时器及其分辨率,否则系统会越来越慢。<br>3. 多媒体定时器在启动时,将自动开辟一个独立的线程。在定时器线程结束之前,注<br>意一定不能再次启动该定时器,不然将迅速造成死机。<br>&nbsp; &nbsp;另外,回调函数必须定义成全局函数或类的静态函数。。。切记,切记!!!
 
如果你把回调函数写成这样就对了<br>procedure CallBack(uTimerID,uMessage:UINT; dwUser,dw1,dw2:Dword) stdcall;<br>begin<br>&nbsp; if i&gt;10000 then exit;<br>&nbsp; inc(i);<br>&nbsp; form1.label1.caption:=inttostr(i);<br>end;<br>
 
多人接受答案了。
 
后退
顶部