一、VC實現高精度定時器__基本流程
1、頭文件包含 #include <MMSystem.h>
2、類成員中添加變量 UINT m_iTimerId; //定時器句柄
3、創建回調函數,響應定時器事件
void CALLBACK CatchTimer
( UINT IDEvent,
UINT uReserved,
DWORD dwUser,
DWORD dwReserved1,
DWORD dwReserved2)
{ //在這里寫定時器事件的處理 }
4、開始啟動定時器
//設置定時器分辨率,1ms
timeBeginPeriod(1);
//產生間隔100毫秒,周期執行的定時器事件;啟動定時器
m_iTimerId=timeSetEvent(1,100,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC);
5、結束使用定時器
//刪除定時器事件
if(m_iTimerId)
timeKillEvent(m_iTimerId);
//清除定時器分辨率
timeEndPeriod(1);
設置兩個時鍾定時器,一個間隔是1毫秒,一個間隔是2秒,
每執行一次,輸出當前系統時鍾值到文件“cure.out”,以 比較此定時器的精確度。
(此程序在中文windows95及Microsoft VC5.0編譯通過。只節取與定時器有關的部分程序。)
#include < stdio.h >
//包含所用系統函數的頭文件,
如果編譯有問題,可調整此語句的位置
#include < mmsystem.h >
//定義1毫秒和2秒時鍾間隔,以毫秒為單位
#define ONE_MILLI_SECOND1
#define TWO_SECOND 2000
//定義時鍾分辨率,以毫秒為單位
#define TIMER_ACCURACY1
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;
}
timeSetEvent函數原型
1 MMRESULT timeSetEvent( UINT uDelay, 2 UINT uResolution, 3 LPTIMECALLBACK lpTimeProc, 4 WORD dwUser, 5 UINT fuEvent ) 6 7 uDelay:以毫秒指定事件的周期。 8 Uresolution:以毫秒指定延時的精度,數值越小定時器事件分辨率越高。缺省值為1ms。 9 LpTimeProc:指向一個回調函數。 10 DwUser:存放用戶提供的回調數據。 11 FuEvent:指定定時器事件類型: 12 TIME_ONESHOT:uDelay毫秒后只產生一次事件 13 TIME_PERIODIC :每隔uDelay毫秒周期性地產生事件。
可以同時設置多個定時器:
1 m_iTimerId = timeSetEvent(1000,1,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC); 2 3 m_iTimerId2 = timeSetEvent(5000,1,CatchTimer,(DWORD)this->m_hWnd,TIME_PERIODIC); 4 5 theApp.id1 = m_iTimerId; 6 theApp.id2 = m_iTimerId2; 7 8 9 void CALLBACK CatchTimer 10 ( UINT IDEvent, 11 UINT uReserved, 12 DWORD dwUser, 13 DWORD dwReserved1, 14 DWORD dwReserved2) 15 { 16 if (IDEvent == theApp.id1) 17 { 18 MessageBoxA(0,"A",0, 0); 19 } 20 else 21 { 22 if (IDEvent == theApp.id2) 23 { 24 MessageBoxA(0,"B",0, 0); 25 } 26 } 27 28 29 static int n = 0; 30 n++; 31 CString str; 32 str.Format("%d", n); 33 theApp.pEdit->SetWindowText(str); 34 35 }