如何使用計時器(Timer)
更新日期:2021/4/8
本頁內容會說明如何以Visual Studio、Visual C++,使用對話方塊形式,撰寫一個使用計時器(Timer)來更新畫面資訊的程式。
主題重點
- 如何啟動 & 停止計時器
- 如何從對話方塊版面上設定計時器的延遲時間
- 如何使用多個計時器
準備工作
請先參考如何建立新的"對話方塊"專案的頁面內容,新建一個"所有選項都使用預設值"的對話方塊專案。
請注意:如果你需要繳交每週的練習成果,請記得將新的對話方塊的"專案名稱",設定成你的學號。以下的範例畫面,對話方塊的專案名稱會使用"MFCTest",你可以把"MFCTest"想像替換為你使用的專案名稱,來找到對應的檔案做修改與測試。
以下的內容在許多步驟都會用到上一個主題"身體質量指數(Body Mass Index, BMI)計算程式範例"曾解說過的操作步驟,如果有疑問,可以開啟該頁面來對照、參考。
1.如何啟動 & 停止計時器
完成新增一個對話方塊專案後,如果沒有發生問題,Visual Studio的備妥畫面如下。
請切換到"資源檢視"視窗,開啟主對話方塊資源(這裡的範例為"IDD_MFCTEST_DIALOG",在你的專案中應該為"IDD_你的專案名稱_DIALOG"),程式編輯畫面會出現這個對話方塊的版面外觀,應該如下圖一樣。
請先選到這個主對話方塊本身,按下滑鼠右鍵,然後在彈出的功能表中選擇"屬性"選項,讓Visual Studio切換到這個主對話方塊的"屬性"視窗。
在對話方塊的屬性視窗中,請把原本無法正確辨識字型的"Font(Size)"項目(預設的顯示內容應該是"????(9)"),設定為你的系統中有內建的字型。這裡的範例是選擇使用"新細明體",字型大小選定為"12"(預設是9)。
然後請用滑鼠選取對話方塊上的三個預設元件:"TODO:在此放置對話方塊控制項。"、"確定(按鈕)"、"取消(按鈕)",按下鍵盤的Delete鍵將他們刪除,因為在後續的範例撰寫中,不會再使用到他們。
接著請在空白的主對話方塊版面上,使用"工具箱"視窗,新增一個"Static Text"、一個"Edit Control"、兩個"Button",新增完成的參考畫面如下。
請修改剛剛新增的一個"Static Text"與兩個"Button"的"Caption"屬性:
* 將"Static Text"的"Caption"屬性修改為"計時器執行次數(次)"
* 第一個"Button"的"Caption"屬性修改為"啟動計時器"
* 第二個"Button"的"Caption"屬性修改為"關閉計時器"
修改完成的顯示畫面應該如下圖。
接著請用滑鼠左鍵,在主對話方塊版面上"點兩次"畫面上的兩個按鈕(每個按鈕各點兩次),為它們加入對應要執行的函式。
為按鈕加入對應要執行的函式後,Visual Studio會自動跳轉到程式碼編輯視窗,顯示這個函式的程式碼區塊,方便我們做後續的修改。加入的函式預設名稱為"OnBnClickedButton1"與"OnBnClickedButton2"。
請切換到主對話方塊編輯畫面,選取"Edit Control",按滑鼠右鍵,在彈出的功能表中選擇"加入變數",會彈出"新增控制變數"的對話方塊,將"新增控制變數"對話方塊的設定值調整成下圖所示。
請切換到"類別檢視"視窗,點選主對話方塊類別(這裏的範例是"CMFCTestDlg",你的應該會是"C你的專案名稱Dlg"),在下半段視窗顯示的資訊中,就可以看到剛剛新增的成員變數(m_iEdit1)與對應兩個Button的成員函式("OnBnClickedButton1"與"OnBnClickedButton2")。
請切換到主對話方塊編輯畫面,選取主對話方塊本身,按滑鼠右鍵,在彈出的功能表中選擇"屬性",讓Visual Studio顯示"屬性視窗"。
點選"屬性視窗"上方的"訊息"按鈕,往下捲動找到名稱為"WM_TIMER"的訊息。訊息名稱的右邊,有一個下拉選單,點選後會出現一行文字"<Add> OnTimer",請點選這行文字,就會替程式專案加入一個名稱為"OnTimer"的函式。
這個函式"OnTimer"會在計時器啟動時、每經過特定的延遲時間就被呼叫執行一次,也就是說如果程式有需要不斷重複執行的工作,可以在這個函式內做處理。
這時切換到"類別檢視"視窗,選取"CMFCTestDlg"類別(請替換成"C你的專案名稱Dlg"),就可以在下半段的列表畫面中,看到剛剛新增的"OnTimer"函式。用滑鼠點選它兩下,就可以在程式碼編輯視窗,顯示"OnTimer"函式的程式碼片段,方便我們進行編修。
請在程式碼編輯視窗,輸入"OnBnClickedButton1"、"OnBnClickedButton2"、"OnTimer"函式中需要的程式碼。程式碼各行代表的意義與功能,請見下圖程式碼上方的綠色註解文字的說明。
完成上面三個部分的程式碼編修後,請按Visual Studio畫面上方、中央的"本機Windows偵錯工具"按鈕,進行修改後的程式編譯、連結。
如果程式碼都沒有輸入錯誤,就可以看到這個對話方塊程式出現在電腦螢幕上。按下"啟動計時器"按鈕,就可以啟用識別編號為1的計時器,然後一直將畫面上計算次數的數值做更新。
因為目前程式碼的設定是讓計時器每延遲1000毫秒(ms)執行一次,也就是一秒執行一次,所以我們看到的數字更新會差不多每秒累計一次。
2.如何從對話方塊版面上設定計時器的延遲時間
剛剛在"OnBnClickedButton1"輸入啟動計時器的程式碼時("SetTimer"這一行),第二個參數是指定計時器的"延遲時間",也就是間隔多少毫秒(ms)要讓計時器函數("OnTimer")執行一次。
我們可以在對話方塊的版面上,新增一個"Edit Control",方便我們在啟動計時器之前,來變更這個"延遲時間"的參數,就可以設定計時器以你需要的速度來執行。
請切換到主對話方塊編輯畫面,按著鍵盤的"Shift"或"Control"鍵,點選"計時器執行次數(次)"這個"Static Text"與它旁邊的"Edit Control",然後按鍵盤的複製鍵("Control + C"),再按下貼上鍵("Control + V"),就可以簡便地複製出一組一樣的"Static Text"與"Edit Control"。
將剛剛複製、貼上的這組"Static Text"與"Edit Control"位置移動、排列整齊,可參照下圖。
將新增的這個"Static Text"的"Caption"屬性,修改為"計時器延遲時間(ms)"。修改畫面請參閱下圖。
選取這個新增的"Edit Control",按滑鼠右鍵,在彈出的功能表中選擇"加入變數",會彈出"新增控制變數"的對話方塊,將"新增控制變數"對話方塊的設定值調整成下圖所示。
這時切換到"類別檢視"視窗,選取"CMFCTestDlg"類別(請替換成"C你的專案名稱Dlg"),就可以在下半段的列表畫面中,看到剛剛新增的"m_uiEdit2"變數。
Visual Studio一般會將新增的成員變數的"預設值"設定為"0"。如果"0"不是一個合適的預設值,我們可以在主對話方塊類別的"建構式"的地方,進行這個預設值的修改。
在"類別檢視"視窗中,用滑鼠左鍵點選兩次建構式名稱(建構式名稱跟類別的名稱相同),會在程式碼編輯視窗顯示建構式的程式碼,可參考下圖。我們可以在這裡看到"m_iEdit1"、"m_uiEdit2"這兩個成員變數,後面還跟著"(0)",括號中的"0",就是預設給定的變數初始值。
請將"m_uiEdit2"後面跟著的括號中的"0",修改成一個合適的數值,例如改成:m_uiEdit2(1000)。修改成"1000"的意思是說,預設延遲1000毫秒(ms)讓計時器函式執行一次。
計時器的延遲時間最小的設定值為"1",也就是1毫秒(ms)執行一次"OnTimer"的函式(理論上是這樣,但個人電腦一般是做不到這麼快的速度...)。數值不可以小於1,也不能有小數點,不然會發生錯誤。
接著請將"OnBnClickedButton1"函式修改如下圖所示。
主要修訂的168行與174行,功能是讓在對話方塊版面上輸入的計時器延遲時間,可以在啟動計時器時,當作第二個參數來調整計時器的運作速度。
程式碼修改完畢後按下Visual Studio畫面上方、中央的"本機Windows偵錯工具"按鈕,編譯執行這個修改過的對話方塊專案,成功的話應該會出現如下的執行畫面。
請試著將計時器的延遲時間輸入不同數值,然後按下"啟動計時器"按鈕,觀察"計時器執行次數"的數字累計速度。
將延遲時間設定為10毫秒,應該可以觀察到比100毫秒或1000毫秒(我們在建構式中預設的值)要快得多。
理論上可以將計時器的延遲時間設定為1毫秒(ms),不過你可以試著觀察看看,執行次數的累計速度明顯跟不上這個"理論上每秒執行1000次"的設定...
3.如何使用多個計時器
啟動計時器使用的函式是SetTimer,在計時器啟動後,每當程式收到"WM_TIMER"的訊息時,"OnTimer"函式就會被呼叫執行一次。
"OnTimer"這個函式有唯一的一個變數,名稱叫"nIDEvent",它是一個沒有負數的整數(UINT),代表目前呼叫"OnTimer"函式的是哪一個識別號碼的計時器訊息。請參考下圖。
也就是說,我們可以藉由檢查這個"nIDEvent"的數值,來判斷在多個計時器同時運作的狀況下,應該要執行哪一個部分的程式碼。
請先切換到對話方塊編輯畫面,將畫面上現有的兩個Static Text、兩個Edit Control、兩個Button全部選取(可以按著滑鼠左鍵、拖曳出一個選取區域,將他們一次全部選到,或是按著鍵盤的Shift或Control鍵,再用滑鼠一個一個點選),然後按下"Control + C"(複製),再按"Control + V"(貼上),新增一組一模一樣的元件。
新增的這組元件可能會與原有的發生重疊,請調整一下他們在對話方塊版面上的位置,將兩組元件的位置錯開,請參考下圖。
畫面上這兩組元件,是要用來做兩個計時器(Timer 1、Timer 2)的個別測試使用。我們可以在"工具箱"視窗,找到一個名稱為"Group Box"的元件,請新增兩個"Group Box"在對話方塊版面上。
"Group Box"的功能主要是用來將畫面上的元件"分組",你可以將新增的這兩個"Group Box"的大小調整一下,讓他們剛好圈住第一群與第二群的元件,請參考下圖。
請再點選到上面這個"Group Box",切換到"屬性"視窗,將它的"Caption"屬性修改為"Timer 1",然後再將下面這個"Group Box"的"Caption"屬性修改為"Timer 2"。
修改完成後"Group Box"左上角的標示文字就會變成我們修改的內容,請參考下圖,這樣可以方便使用者區分這些畫面上的元件。
接著要將新增的兩個Edit Control(他們的ID應該會是"IDC_EDIT3"與"IDC_EDIT4"),加入對應的成員變數。
請先點選"Timer 2"群組中,上面的那個Edit Control(ID是"IDC_EDIT3"),按滑鼠右鍵,在彈出的功能表中選擇"加入變數",會彈出"新增控制變數"的對話方塊,將"新增控制變數"對話方塊的設定值調整成下圖所示。
再先點選"Timer 2"群組中,下面的那個Edit Control(ID是"IDC_EDIT4"),按滑鼠右鍵,在彈出的功能表中選擇"加入變數",會彈出"新增控制變數"的對話方塊,將"新增控制變數"對話方塊的設定值調整成下圖所示。
最後再將"Timer 2"群組中的兩個Button,各用滑鼠左鍵點選兩下,為他們加入被按下時要執行的函式(名稱會是"OnBnClickedButton3"與"OnBnClickedButton4")。
此時如果切換到"類別檢視"視窗,點選主對話方塊類別後,可以在下半段的顯示資訊中看到剛剛加入的變數(m_iEdit3與m_uiEdit4)與函式("OnBnClickedButton3"與"OnBnClickedButton4")。
用滑鼠左鍵點選兩下m_iEdit3或m_uiEdit4,就會開啟類別定義的檔案(這裡是"MFCTestDlg.h",在你的專案中應該是"你的專案名稱Dlg.h"),在裡面可以看到剛剛加入的變數與函式的宣告程式碼(下圖中的第42~47行)。
接著請用滑鼠左鍵,在"類別檢視"視窗中,點選"建構式"的名稱兩次(這裡是"CMFCTestDlg",在你的專案中建構式的名稱應該是"你的專案名稱Dlg"),開啟"建構式"的程式碼來進行編修。
要修改的部分是下圖的第58行,請將預設的計時器2的延遲時間,設定為一個大於"1"的數值(預設是"0",會發生錯誤)。這裡的範例是將它修改為"100",以便跟計時器1的延遲時間有比較明顯的區隔(這裡計時器1的預設是"1000"),在後面測試程式時可以方便觀察分辨兩個計時器有不同的運作速度。
接著請在"類別檢視"視窗中,用滑鼠左鍵點選兩次"OnBnClickedButton3"函式名稱,Visual Studio會捲動到這段程式碼區塊來讓我們編修。
請參照下圖,把第219 ~ 226行的程式碼輸入到"OnBnClickedButton3"函式區塊中,並把第233 ~ 234行的程式碼輸入到"OnBnClickedButton4"的函式區塊。你也可以直接複製在"OnBnClickedButton1"與"OnBnClickedButton2"已經輸入過的程式碼,貼到對應的區塊中再做小部分的修改。
最後請捲動到OnTimer的函式區塊,將程式碼修改為如下圖第195 ~ 212行。
這樣每次OnTimer函式被呼叫執行時,裡面就可以識別此時應該要執行哪一個編號的計時器程式碼,在多個計時器同時使用時,也不會造成相互干擾。
程式碼修改完畢後按下Visual Studio畫面上方、中央的"本機Windows偵錯工具"按鈕,編譯執行這個修改過的對話方塊專案,成功的話應該會出現如下的執行畫面。
你可以啟動任一個計時器,或同時啟動兩個計時器,他們個別的執行次數會分別累計,不會相互干擾。中途停止或重新啟動其中一個,也不會干擾到另一個計時器的運作。
本次的計時器(Timer)程式範例到此結束。
如果你是修課同學,請將這個練習專案程式碼資料夾中不需要的檔案都刪除後(可參照 如何替專案"瘦身" & 備份專案),把剩餘的程式碼以壓縮軟體(zip 或 rar 皆可)壓縮成一個檔案,再將這個檔案email給老師,當作你本週學習成果的確認。
本週的壓縮檔案email繳交的時限,**請在下一週的週五(2021/4/16) 13:00前完成,逾時算缺交**,請把握時間完成。
歡迎社群分享。若要全文轉載,請先來信詢問。禁止修改內文,禁止商業使用,必須註明來自「太陽部落」及附上原文連結:https://sunblogsws.blogspot.com/2020/04/vs-timer.html
留言