日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

Visual C++——定时器(计时器)SetTimer函数

發布時間:2024/8/1 c/c++ 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Visual C++——定时器(计时器)SetTimer函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本概念?

SetTimer函數用于創建一個計時器

KillTimer函數用于銷毀一個計時器。

計時器屬于系統資源,使用完應及時銷毀。?

API?

SetTimer的函數原型:?

UINT_PTR SetTimer(?HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, TIMERPROC lpTimerFunc )?;?

其中?

hWnd是和timer關聯的窗口句柄,此窗口必須為調用SetTimer的線程所有;如果hWnd為NULL,沒有窗口和timer相關聯并且nIDEvent參數被忽略?

nIDEvent是timer的標識,為非零值;如果hWnd為NULL則被忽略;如果hWnd非NULL而且與timer相關聯的窗口已經存在一個為此標識的timer,則此次SetTimer調用將用新的timer代替原來的timer。timer標識和窗口相關,兩個不同的窗口可以擁有nIDEvent相同的tiemr?

uElapse是以毫秒指定的計時間隔值,范圍為1毫秒到4,294,967,295毫秒(將近50天),這個值指示Windows每隔多久時間給程序發送WM_TIMER消息。?

lpTimerFunc是一個回調函數的指針,俗稱TimerFunc;如果lpTimerFunc為NULL,系統將向應用程序隊列發送WM_TIMER消息;如果lpTimerFunc指定了一個值,DefWindowProc將在處理WM_TIMER消息時調用這個lpTimerFunc所指向的回調函數,因此即使使用TimerProc代替處理WM_TIMER也需要向窗口分發消息。?

返回值:如果hWnd為NULL,返回值為新建立的timer的ID,如果hWnd非NULL,返回一個非0整數,如果SetTimer調用失敗則返回0?

KillTimer的函數原型:

BOOL KillTimer( HWND hWnd, UINT_PTR uIDEvent ) ;

參數意義同SetTimer。?

關于KillTimer對消息隊列中剩余未處理的WM_TIMER消息的影響,MSDN和Programming Windows上的說法完全相反。

MSDN:

The KillTimer function does not remove WM_TIMER messages already posted to the message queue. 而petzold則說 The KillTimer call purges the message queue of any pending WM_TIMER messages. Your program will never receive a stray WM_TIMER message following a KillTimer call. (KillTimer消除消息隊列中任何未處理的WM_TIMER消息,調用KillTimer后你的程序永遠不會收到一條“漂泊游蕩”的WM_TIMER消息)?

關于WM_TIMER消息?

wParam為計時器的ID;

如果需要設定多個計時器,那么對每個計時器都使用不同的計時器ID。

wParam的值將隨傳遞到窗口過程中的WM_TIMER消息的不同而不同。?

lParam為指向TimerProc的指針,如果調用SetTimer時沒有指定TimerProc(參數值為NULL),則lParam為0(即NULL)。?
可以通過在窗口過程中提供一個WM_TIMER case處理這個消息,或者,默認窗口過程會調用SetTimer中指定的TimerProc來處理WM_TIMER消息?

使用方法

如果在程序的整個執行過程中使用計時器,一般在處理WM_CREATE消息時或WinMain中消息循環前調用SetTimer,在處理WM_DESTROY消息時或在WinMain中消息循環后return前調用KillTimer。根據SetTimer中的參數不同,有三種方法使用計時器。?

方法一

調用SetTimer時指定窗口句柄hWnd,nIDEvent中指定計時器ID,將lpTimerFunc置NULL從而不使用TimerProc;

在窗口過程中處理WM_TIMER消息。

調用KillTimer時,使用SetTimer中指定的hWnd和id。

最好使用#define定義timer的id,例如:?

#define ID_TIMER 1? SetTimer(hWnd,ID_TIMER,1000,NULL) ;? KillTimer(hWnd,ID_TIMER) ;?

方法二

調用SetTimer時指定窗口句柄hWnd,nIDEvent中指定計時器ID,lpTimerFunc參數不為NULL而指定為TimerProc函數的指針。

這種方法使用TimerProc函數(名字可自定)處理WM_TIMER消息:?

VOID CALLBACK TimerProc ( HWND hwnd, UINT message, UINT iTimerID, DWORD dwTime)? {? //處理WM_TIMER訊息? }?

TimerProc的參數hwnd是在調用SetTimer時指定的窗口句柄。

Windows只把WM_TIMER消息送給TimerProc,因此消息參數總是等于WM_TIMER。

iTimerID值是計時器ID,dwTimer值是與從GetTickCount函數的返回值相容的值。這是自Windows啟動后所經過的毫秒數。

使用這種方法時,相關函數調用的形式為:?

SetTimer(hWnd,ID_TIMER,1000,TimerProc) ;? KillTimer(hWnd,ID_TIMER) ;?

方法三

調用SetTimer時不指定窗口句柄(為NULL),iTimerID參數自然被忽略,lpTimerFunc不為NULL而指定為TimerProc的指針。正如上面SetTimer的討論中所說的,此時SetTimer的返回值正是新建立的計時器的ID,需將這個ID保存以供KillTimer銷毀計時器時所用。當然,KillTimer的hWnd參數也置為NULL。這種方法同樣用TimerProc處理WM_TIMER消息。?

UINT_PTR iTimerID ;? iTimerID = SetTimer(NULL,0,1000,TimerProc) ;? KillTimer(NULL,iTimerID) ;?

使用這種方法的好處是不必自己指定計時器ID,這樣就不必擔心用錯ID。?

使用多個計時器?

使用多個計時器只要在建立計時器時指定不同的ID。

比如用上面所述方法一時的情況:?

#define TIMER_SEC 1? #define TIMER_MIN 2? 然后使用兩個SetTimer來設定兩個計時器:? SetTimer (hwnd, TIMER_SEC, 1000, NULL) ;? SetTimer (hwnd, TIMER_MIN, 60000, NULL) ;? WM_TIMER的處理如下所示:? case WM_TIMER:? switch (wParam)? {? case TIMER_SEC:?//每秒一次的處理?break ;? case TIMER_MIN:?//每分鐘一次的處理?break ;? }? return 0 ;?

改變計時器的時間間隔?

如果想將一個已經存在的計時器設定為不同的時間間隔,可以簡單地用不同的時間值再次調用SetTimer。?
?

常見問題?

計時器精確嗎??

計時器并不精確。有兩個原因:?

原因一:Windows計時器是硬件和ROM BIOS架構下之計時器一種相對簡單的擴充。回到Windows以前的MS-DOS程序寫作環境下,應用程式能夠通過攔截者稱為timer tick的BIOS中斷來實現時鐘或計時器。一些為MS-DOS編寫的程序自己攔截這個硬件中斷以實現時鐘和計時器。這些中斷每54.915毫秒產生一次,或者大約每秒18.2次。這是原始的IBM PC的微處理器頻率值4.772720 MHz被218所除而得出的結果。在Windows 98中,計時器與其下的PC計時器一樣具有55毫秒的解析度。在Microsoft Windows NT中,計時器的解析度為10毫秒。Windows應用程式不能以高于這些解析度的頻率(在Windows 98下,每秒18.2次,在Windows NT下,每秒大約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秒。

?WM_TIMER消息無法響應

https://bbs.csdn.net/topics/300035118?list=lz

參考文章

http://www.studynew.com/study/vc/2004082519380331684.html

http://blog.sina.com.cn/s/blog_5a6f39cf010148xy.html

https://blog.csdn.net/u012104827/article/details/105278079/

https://blog.csdn.net/lcalqf/article/details/53020009

總結

以上是生活随笔為你收集整理的Visual C++——定时器(计时器)SetTimer函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。