一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Windows WM_TIMER消息

 VoidOc 2013-10-26

Windows定時器是一種周期性的消息產(chǎn)生裝置,它會每隔一段指定時間發(fā)送一次定時消息WM_TIMER。它是一個很重要的系統(tǒng)消息,當(dāng)系統(tǒng)所設(shè)置的時間到達(dá)以后,系統(tǒng)就會自動發(fā)送該消息。與該消息聯(lián)系密切的函數(shù)是SetTimer(),它設(shè)置一個系統(tǒng)時鐘,當(dāng)設(shè)置的時間到時,系統(tǒng)產(chǎn)生WM_TIMER消息。通過對SetTimer()函數(shù)的參數(shù)進(jìn)行設(shè)置,可以告訴用戶哪一個時鐘的時間到了。因此,可以將一些周期性的工作放入WM_TIMER的消息處理函數(shù)中。

定時器的使用一般遵循下列步驟:

(1)使用SetTimer()函數(shù)設(shè)置定時器

SetTimer()函數(shù)的原型如下:

 

UINT SetTimer(UINT nIDEvent, UINT nElapse, void (CALLBACK EXPORT*lpfnTimer)(HWND,UINT, UINT, DWORD));

 

其中,參數(shù)nIDEvent為新創(chuàng)建的定時器標(biāo)識號碼(非零),當(dāng)一個應(yīng)用程序需要多個定時器時,靠此參數(shù)的不同來加以區(qū)別;參數(shù)nElapse為定時器間隔,以毫秒為單位,當(dāng)由該參數(shù)規(guī)定的時間到后,系統(tǒng)發(fā)送WM_TIMER消息;參數(shù)lpfnTimer為指定處理消息WM_TIMER的函數(shù),通常為NULL時,表示由CWnd對象的OnTimer成員函數(shù)來處理該消息,當(dāng)然也可以超載該函數(shù)。

如果創(chuàng)建成功,則返回新的定時器的號碼:否則返回0。

(2)超載OnTimer()函數(shù),完成用戶希望的操作

通過第一步設(shè)置的定時器會按其設(shè)置的時間間隔向應(yīng)用程序發(fā)送WM_TIMER消息,為了接收和處理該消息,應(yīng)超載消息處理函數(shù)OnTimer()(可以由ClassWizard自動產(chǎn)生),其函數(shù)原型如下:

 

afx_msg void OnTimer(UINT nIDEvent);

 

其中,參數(shù)nIDEvent為定時器的標(biāo)識。若在程序中設(shè)置了多個定時器時,靠此參數(shù)的不同來加以區(qū)別。

(3)撤銷定時器

CWnd::KillTimer
    BOOL KillTimer( int nIDEvent );
    返回值:
      指定了函數(shù)的結(jié)果。如果事件已經(jīng)被銷毀,則返回值為非零值。如果KillTimer成員函數(shù)不能找到指定的定時器事件,則返回0。
    參數(shù):

nIDEvent傳遞給SetTimer的定時器事件值。
傳遞給SetTimer的定時器事件值。


   說明:
銷毀以前調(diào)用SetTimer創(chuàng)建的用nIDEvent標(biāo)識的定時器事件。任何與此定時器有關(guān)的未處理的WM_TIMER消息都從消息隊列中清除。



 

定時器使用完后,可以通過調(diào)用KillTimer()函數(shù)來清除定時器,其函數(shù)原型如下:

 

BOOL KillTimer(int nIDEvent);

 

其中,參數(shù)nIDEvent為準(zhǔn)備清除的定時器號碼,該參數(shù)的值必須在SetTimer()函數(shù)中設(shè)置過,即不能夠清除一個不存在的定時器號碼。

【例9.4 本程序在例9.3程序的基礎(chǔ)上增加定時器的功能。當(dāng)按B鍵時,啟動定時器,屏幕上的圖形自動移動;當(dāng)按S鍵時,撤銷定時器,停止自動移動。 程序演示

(1)在字符消息映射函數(shù)中添加啟動和撤銷定時器的代碼

 

void CKeyMsgView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)

{

switch(nChar)

{

case 'b':

case 'B':

SetTimer(1,100,NULL); //建立一號定時器,時間間隔為100ms

break;

case 's':

case 'S':

KillTimer(1); //撤銷一號定時器

break;

}

}

 

(2)添加WM_TIMER的消息映射函數(shù)OnTimer()的實現(xiàn)代碼

 

void CKeyMsgView::OnTimer(UINT nIDEvent)

{

//圖形往右下角自動移動

CRect OldRect=m_Rect;

m_Rect.OffsetRect(CPoint(1,1)); //圖形往右下角移動一個像素

OldRect.UnionRect(OldRect,m_Rect);

InvalidateRect(OldRect); //將指定矩形區(qū)域OldRect的內(nèi)容刷新

CView::OnTimer(nIDEvent);

}

 

TimerProc函數(shù)是一個應(yīng)用程序定義的回調(diào)函數(shù),用于處理WM_TIMER消息。

 

函數(shù)原型:

VOID CALLBACK TimerProc(

    HWND hwnd, // 定時器消息的窗口句柄

    UINT uMsg,    // WM_TIMER 消息

    UINT idEvent, // 定時器標(biāo)識符

    DWORD dwTime   // 當(dāng)前系統(tǒng)時間

   );

 

參數(shù)說明:

hwnd

       標(biāo)識了與定時器進(jìn)行關(guān)聯(lián)的窗口。 

uMsg

       指定WM_TIMER消息。

idEvent

       指定定時器的標(biāo)識符。 

dwTime

       指定自窗口啟動開始所經(jīng)過的毫秒數(shù)。這是GetTickCount函數(shù)的返回值。

返回值: 

       這個函數(shù)沒有返回值。

備注: 

TimerProc是一個應(yīng)用程序定義函數(shù)名稱的占位符。

 

 

百度知道:

SetTimer函數(shù)的用法  1 )用WM_TIMER來設(shè)置定時器

  先請看SetTimer這個API函數(shù)的原型

  UINT_PTR SetTimer(

  HWND hWnd, // 窗口句柄

  UINT_PTR nIDEvent, // 定時器ID,多個定時器時,可以通過該ID判斷是哪個定時器

  UINT uElapse, // 時間間隔,單位為毫秒

  TIMERPROC lpTimerFunc // 回調(diào)函數(shù)

  );

  例如

  SetTimer(m_hWnd,1,1000,NULL); //一個1秒觸發(fā)一次的定時器

  在MFC程序中SetTimer被封裝在CWnd類中,調(diào)用就不用指定窗口句柄了

  于是SetTimer函數(shù)的原型變?yōu)椋?/font>

  UINT SetTimer(UINT nIDEvent,UINT nElapse,void(CALLBACK EXPORT *lpfnTimer)(HWND,UINT ,UINT ,DWORD))

  當(dāng)使用SetTimer函數(shù)的時候,就會生成一個計時器。函數(shù)中nIDEvent指的是計時器的標(biāo)識,也就是名字。nElapse指的是時間間隔,

  也就是每隔多長時間觸發(fā)一次事件。第三個參數(shù)是一個回調(diào)函數(shù),在這個函數(shù)里,放入你想要做的事情的代碼,你可以將它設(shè)定為NULL,

  也就是使用系統(tǒng)默認(rèn)的回調(diào)函數(shù),系統(tǒng)默認(rèn)認(rèn)的是onTime函數(shù)。這個函數(shù)怎么生成的呢?你需要在需要計時器的類的生成onTime函數(shù):

  在ClassWizard里,選擇需要計時器的類,添加WM_TIME消息映射,就自動生成onTime函數(shù)了。然后在函數(shù)里添加代碼,讓代碼實現(xiàn)功能。

  每隔一段時間就會自動執(zhí)行一次。

  SetTimer計時器是系統(tǒng)資源,使用完畢應(yīng)及時用KillTimer銷毀,關(guān)于SetTimer的返回值:如果hWnd為NULL,返回值為新建立的timer的ID,如果hWnd非NULL,返回一個非0整數(shù),如果SetTimer調(diào)用失敗則返回0 ,簡言之,SetTimer的返回值用于將來的銷毀。

  改變計時器的時間間隔

  如果想將一個已經(jīng)存在的計時器設(shè)定為不同的時間間隔,可以簡單地用不同的時間值再次調(diào)用SetTimer。

  計時器精確嗎?

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

  原因一:Windows計時器是硬件和ROM

  BIOS架構(gòu)下之計時器一種相對簡單的擴充?;氐絎indows以前的MS-DOS程序?qū)懽鳝h(huán)境下,應(yīng)用程式能夠通過攔截者稱為timer

  tick的BIOS中斷來實現(xiàn)時鐘或計時器。一些為MS-DOS編寫的程序自己攔截這個硬件中斷以實現(xiàn)時鐘和計時器。這些中斷每54.915毫秒產(chǎn)生一次,或者大約每秒18.2次。這是原始的IBM

  PC的微處理器頻率值4.772720 MHz被218所除而得出的結(jié)果。在Windows

  98中,計時器與其下的PC計時器一樣具有55毫秒的解析度。在Microsoft Windows

  NT中,計時器的解析度為10毫秒。Windows應(yīng)用程式不能以高于這些解析度的頻率(在Windows 98下,每秒18.2次,在Windows

  NT下,每秒大約100次)接收WM_TIMER消息。在SetTimer中指定的時間間隔總是截尾后tick數(shù)的整數(shù)倍。例如,1000毫秒的間隔除以54.925毫秒,得到18.207個tick,截尾后是18個tick,它實際上是989毫秒。對每個小于55毫秒的間隔,每個tick都會產(chǎn)生一個WM_TIMER消息。

  可見,計時器并不能嚴(yán)格按照指定的時間間隔發(fā)送WM_TIMER消息,它總要相差那么幾毫秒。

  即使忽略這幾個毫秒的差別,計時器仍然不精確。請看原因二:

  WM_TIMER消息放在正常的消息隊列之中,和其他消息排列在一起,因此,如果在SetTimer中指定間隔為1000毫秒,那么不能保證程序每1000毫秒或者989毫秒就會收到一個WM_TIMER消息。如果其他程序的執(zhí)行事件超過一秒,在此期間內(nèi),您的程式將收不到任何WM_TIMER訊息。事實上,

  Windows對WM_TIMER消息的處理非常類似于對WM_PAINT消息的處理,這兩個消息都是低優(yōu)先級的,程序只有在消息隊列中沒有其他消息時才接收它們。

  WM_TIMER還在另一方面和WM_PAINT相似:Windows不能持續(xù)向消息隊列中放入多個WM_TIMER訊息,而是將多余的WM_TIMER消息組合成一個消息。因此,應(yīng)用程序不會一次收到多個這樣的消息,盡管可能在短時間內(nèi)得到兩個WM_TIMER消息。應(yīng)用程序不能確定這種處理方式所導(dǎo)致的WM_TIMER消息「遺漏」的數(shù)目。

  可見,WM_TIMER消息并不能及時被應(yīng)用程序所處理,WM_TIMER在消息隊列中的延誤可能就不能用毫秒來計算了。

  由以上兩點,你不能通過在處理WM_TIMER時一秒一秒計數(shù)的方法來計時。如果要實現(xiàn)一個時鐘程序,可以使用系統(tǒng)的時間函數(shù)如GetLocalTime

  ,而在時鐘程序中,計時器的作用是定時調(diào)用GetLocalTime獲得新的時間并刷新時鐘畫面,當(dāng)然這個刷新的間隔要等于或小于1秒。

例:

  1) 不用回調(diào)函數(shù)

  SetTimer(1,1000,NULL);

  1:計時器的名稱;

  1000:時間間隔,單位是毫秒;

  NULL:使用onTime函數(shù)。

  當(dāng)不需要計時器的時候調(diào)用KillTimer(nIDEvent);

  例如:KillTimer(1);

  2) 調(diào)用回調(diào)函數(shù)

  此方法首先寫一個如下格式的回調(diào)函數(shù)

  void CALLBACK TimerProc(HWND hWnd,UINT nMsg,UINT nTimerid,DWORD dwTime);

  然后再用SetTimer(1,100,TimerProc)函數(shù)來建一個定時器,第三個參數(shù)就是回調(diào)函數(shù)地址。

  或許你會問,如果我要加入兩個或者兩個以上的 timer怎么辦?

  繼續(xù)用SetTimer函數(shù)吧,上次的timer的ID是1,這次可以是2,3,4。。。。

  SetTimer(2,1000,NULL);

  SetTimer(3,500,NULL);

  嗯,WINDOWS會協(xié)調(diào)他們的。當(dāng)然onTimer函數(shù)體也要發(fā)生變化,要在函數(shù)體內(nèi)添加每一個timer的處理代碼:

  onTimer(nIDEvent)

  {

  switch(nIDEvent)

  {

  case 1:........;

  break;

  case 2:.......;

  break;

  case 3:......;

  break;

  }

  }

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    风韵人妻丰满熟妇老熟女av| 东京热男人的天堂一二三区| 日本大学生精油按摩在线观看| 青青久久亚洲婷婷中文网| 欧美一区二区口爆吞精| 99免费人成看国产片| 欧美日韩国产欧美日韩| 国产精品尹人香蕉综合网| 国产原创激情一区二区三区| 久久国产精品亚州精品毛片 | 久久本道综合色狠狠五月| 日本丁香婷婷欧美激情| 午夜福利精品视频视频| 人妻久久一区二区三区精品99| 黄片在线免费看日韩欧美| 欧美成人久久久免费播放| 中文字幕佐山爱一区二区免费| 亚洲av日韩av高潮无打码| 国产一区二区三中文字幕| 亚洲中文字幕在线综合视频| 欧美乱妇日本乱码特黄大片| 精品午夜福利无人区乱码| 在线免费国产一区二区三区| 国内精品偷拍视频久久| 东京热男人的天堂社区| 美女被后入福利在线观看| 国产精品一区欧美二区| 欧美尤物在线观看西比尔| 91香蕉国产观看免费人人| 精品女同在线一区二区| 亚洲黄片在线免费小视频| 丝袜破了有美女肉体免费观看 | 国产传媒免费观看视频| 久草热视频这里只有精品| 青青操精品视频在线观看| 黄色激情视频中文字幕| 高清欧美大片免费在线观看| 九九热视频经典在线观看| 亚洲综合香蕉在线视频| 国产成人精品一区二区在线看| 亚洲中文字幕高清视频在线观看|