转贴:
        Win32 API函数库中已经为用户提供了一组用于高精度计时的底层函数,如果用户使用得当,计时精度可到1ms。这个计时精度,对于一般的实时系统控制完全可以满足要求。现将由BCB提供的重新封装后的一组与时间相关的主要接口函数(函数名、参数、功能与Win32API基本相同)说明如下:            1.DWORD timeGetTime(void) 
                   返回从Windows启动开始经过的毫秒数。最大值为2的32次方,约49.71天。
                    2.MMRESULT timeSetEvent(UINT uDelay,UINT uResolution,LPTIMECALLBACK 
        lpTimeProc,DWORD dwUser,UINTfuEvent)            该函数设置一个定时回调事件,此事件可以是一个一次性事件或周期性事件。事件一旦被激活,便调用指定的回调函数,成功后返回事件的标识代码,否则返回NULL.参数说明如下:
                    uDelay:以毫秒制定事件的周期。            UResolution:以毫秒指定延时的精度,数值越小定时器事件分辩率越高。缺省值为1ms. 
                    LpTimeProc:指向一个回调函数。            DwUser:存放用户提供的回调数据。            FuEvent:指定定时器事件类型:TIME_ONESHOT:uDelay毫秒后只产生一次事件。
                                                
        TIME_PERIODIC:每隔uDelay毫秒周期性地产生事件。            3.MMRESULT timeKillEvent(UINT uTimerID) 
                   该函数取消一个指定的定时器回调事件。uTimerID标识要取消的事件(由timeSetEvent函数返回的标识符)。如果定时器时间不存在则返回MMSYSERR_INVALPARAM。
                    void CALLBACK TimeProc(UINT uID,UINT uMsg,DWORD dwUser,DWORD dw1,DWORD dw2);            该函数是一个应用程序定义的回调函数,出现定时器事件时该函数被调用。TimeProc是应用程序定义的函数名的占位符。使用该函数时要注意的是,它只能调用以下有限的几组API函数:PostMessage, 
        timeGetSystemTime, timeGetTime, timeSetEvent, timeKillEvent, midiOutShortMsg, 
        midiOutLongMsg, OutputDebugString。同时也不要使用完成时间很长的API函数,程序尽可能简短。
                   使用以上一组函数就可以完成毫秒级精度的计时和控制(在BCB使用时要将头文件mmsystem.h加到程序中)。由于将定时控制精确到几毫秒,定时器事件将占用大量的CPU时间和系统资源,所以在满足控制要求的前提下,应尽量将参数uResolution的数值增大。而且定时器实时控制功能完成后要尽快释放。
      
 二、Windows 
        95中的定时器的应用(李振)           在windows95编程中有时要用到定时器的功能,大家常用的是通过SetTimer函数设置一个定时器,在事件WM_TIMER响应函数中处理,然后用KillTimer 函数取消此定时器。但此种方式的定时器只能精确到大约55毫秒,对于55毫秒以下的时间精度便无能为力。          笔者在这里向大家提供一个可以精确到1毫秒的定时器——多媒体定
       时器。它主要通过以下函数来实现:        ---- timeBeginPeriod——建立应用程序使用的定时器分辨率;
      
  ---- timeEndPeriod——清除前面用timeBeginPeriod函数建立的最小定时器分
       辨率;        ---- timeSetEvent——产生一个在指定的时间或时间周期间隔内执行的定时器事
       件;
      
  ---- timeKillEvent——删除前面用timeSetEvent产生的定时器事件;
      
  ---- timeGetDevCaps——返回关于定时器服务能力的信息。
      
  ----下面就结合一段程序来具体说明它的用法。这段程序的主要功能是:设置两个时钟定时器,一个间隔是1毫秒,一个间隔是2秒,每执行一次,输出当前系统时钟值到文件“cure.out”,以比较此定时器的精确度。(此程序在中文windows95及Microsoft VC5.0 
       编译通过。只节取与定时器有关的部分程序。)
      
                      
        #include < stdio.h > 
      
                      
        //包含所用系统函数的头文件,如果编译有问题,可调整此语句的位置
      
                      
        #include < mmsystem.h > 
      
                      
        //定义1毫秒和2秒时钟间隔,以毫秒为单位
      
                      
        #define ONE_MILLI_SECOND 1 
      
                      
        #define TWO_SECOND      2000 
      
                      
        //定义时钟分辨率,以毫秒为单位
      
                      
        #define TIMER_ACCURACY 1 
      
                      
        UINT wTimerRes_1ms,wTimerRes_2s;  //定义时间间隔
      
                      
        UINT wAccuracy;//定义分辨率
      
                      
        UINT TimerID_1ms,TimerID_2s;//定义定时器句柄
      
                      
        CCureApp::CCureApp(): fout("cure.out", ios::out)//打开输出文件“cure.out”
      
                      
        { 
      
                              
        // TODO: add construction code here, 
      
                              
        // Place all significant 
      
                             
        initialization in InitInstance 
      
                      
        //给时间间隔变量赋值
      
                              
        wTimerRes_1ms = ONE_MILLI_SECOND        
        ; 
      
                              
        wTimerRes_2s = TWO_SECOND; 
      
                      
        TIMECAPS        tc; 
      
                      
        //通过函数timeGetDevCaps取出系统的分辨率取值范围(对intel系统,
      
                      
        1~16毫秒),//如果无错则继续
      
                      
        if(timeGetDevCaps(&tc, sizeof(TIMECAPS))== TIMERR_NOERROR) 
      
                      
        { 
      
                      
        //分辨率的值不能超出系统的取值范围
      
                      
        wAccuracy = min(max(tc.wPeriodMin, 
      
                      
        TIMER_ACCURACY),tc.wPeriodMax); 
      
                      
        //调用timeBeginPeriod函数设置定时器的分辨率,类似于for循环的步长
      
                      
        timeBeginPeriod(wAccuracy); 
      
                      
        //设置定时器
      
                      
        InitializeTimer(); 
      
                        
        } 
      
                      
        } 
      
                      
        CCureApp::~CCureApp() 
      
                      
        { 
      
                              
        //结束时钟
      
                              
        fout < <  "结束时钟" < <  endl; 
      
                              
        //删除两个定时器
      
                              
        timeKillEvent(TimerID_1ms); 
      
                              
        timeKillEvent(TimerID_2s); 
      
                              
        //删除设置的分辨率
      
                              
        timeEndPeriod(wAccuracy); 
      
                      
        } 
      
 注:使用完的定时器及分辨率一定要删除,否则系统会越来越慢。
      
                      
        void    CCureApp::InitializeTimer() 
      
                      
        { 
      
                              
        StartOneMilliSecondTimer(); 
      
                              
        StartTwoSecondTimer(); 
      
                      
        } 
      
                      
        //一毫秒定时器的回调函数,类似于中断处理程序
      
                      
        voidPASCAL//一定要声明为全局PASCAL函数,否则编译会有问题
      
                      
        OneMilliSecondProc(UINT wTimerID, UINT msg, 
      
                      
        DWORD   dwUser, DWORD dw1, DWORD dw2) 
      
                      
        { 
      
                              
        static  int     ms = 0;//定义计数器
      
                              
        CCureApp        *app = (CCureApp *)dwUser; 
      
                              
        //取得系统时间以毫秒为单位
      
                      
        DWORD osBinaryTime = GetTickCount(); 
      
                      
        //输出计数器值和当前系统时间到文件
      
                              
        app- >fout < <  ++ms < <  ": 1ms : " 
      
                       
        < <  osBinaryTime < <  endl; 
      
                      
        } 
      
                      
        //加装1毫秒定时器
      
                      
        void    CCureApp::StartOneMilliSecondTimer() 
      
                      
        { 
      
                      
        if((TimerID_1ms = timeSetEvent(wTimerRes_1ms, wAccuracy,
      
                       
        (LPTIMECALLBACK) OneMilliSecondProc,//回调函数
      
                       
        (DWORD)this,//用户自传送到回调函数的数据
      
                      
        /*周期调用,只使用一次用TIME_ONESHOT*/ 
      
                      
        TIME_PERIODIC)) == 0) 
      
                      
        { 
      
                      
        AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); 
      
                      
        } 
      
                      
        else//不等于0表明加装成功,返回此定时器的句柄
      
                      
        fout < <  "16ms计时:" < <  endl; 
      
                      
        } 
      
    以下为2秒定时器的回调函数和加装函数,与1毫秒的类似;
      
                      
        void    PASCAL TwoSecondProc(UINT      
        wTimerID, UINT msg, 
      
                        
        DWORD dwUser, DWORD dw1, DWORD dw2) 
      
                      
        { 
      
                              
        static  int     s = 0; 
      
                              
        CCureApp        *app = (CCureApp *)dwUser; 
      
                              
        DWORD osBinaryTime = GetTickCount(); 
      
                              
        app- >fout < <  "***********************" < <  
        endl; 
      
                              
        app- >fout < <  ++s < <  ": 2s : " < <  
        osBinaryTime < <  endl; 
      
                      
        } 
      
                      
        void    CCureApp::StartTwoSecondTimer() 
      
                      
        { 
      
                      
        if((TimerID_2s = timeSetEvent(wTimerRes_2s, wAccuracy, 
      
                       
        (LPTIMECALLBACK) TwoSecondProc, (DWORD)this, 
      
                        
        TIME_PERIODIC)) == 0) 
      
                      
        { 
      
                      
        AfxMessageBox("不能计时", MB_OK | MB_ICONASTERISK); 
      
                      
        } 
      
                      
        else 
      
                      
        fout < <  "2s计时:" < <  endl; 
      
                      
        }