MFC積累整理

一、定時器Timer

1.MFC方式

(a)創建方法:

資源視圖->類嚮導->消息->WM_TIMER->添加處理程序,即可自動生成相應的函數
xx.h 中自動生成:
afx_msg void OnTimer(UINT_PTR nIDEvent);
xx.cpp中如下所示

  • 消息映射(宏定義)自動新增一條ON_WM_TIMER():
    BEGIN_MESSAGE_MAP(CPannelTransBill, CDialogEx)
    	xxx
    	ON_WM_TIMER()
    END_MESSAGE_MAP()
    
  • 功能函數自動構建:
    void CExample::OnTimer(UINT_PTR nIDEvent)
    {
    	// TODO: 在此添加消息處理程序代碼和/或調用默認值
    
    	CDialogEx::OnTimer(nIDEvent);
    }
    

(b)使用方法:

如需在BeginTimer函數中調用本對話框中的定時器,使用SetTimer(UINT_PTR nIDEvent, UINT nElapse,
void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD))方法即可:

void CExample::BeginTimer()
{
	//啓動ID爲1的定時器,定時1000ms(1s)
	SetTimer(1,1000,null);
}

使用到此結束

  • SetTimer(x,x,x)函數原型:
    啓動定時器就需要使用CWnd類的成員函數SetTimer。CWnd::SetTimer的原型如下:
    UINT_PTR SetTimer(         
       UINT_PTR nIDEvent, //定時器ID
       UINT nElapse,  //定時時間(ms)
    	void (CALLBACK* lpfnTimer)(HWND, UINT, UINT_PTR, DWORD)//回調函數,沒有可設爲NULL
    );
    
    • 參數nIDEvent指定一個非零的定時器ID;參數nElapse指定間隔時間,單位爲毫秒;參數lpfnTimer指定一個回調函數的地址,如果該參數爲NULL,則WM_TIMER消息被髮送到應用程序的消息隊列,並被CWnd對象處理。如果此函數成功則返回一個新的定時器的ID,我們可以使用此ID通過KillTimer成員函數來銷燬該定時器,如果函數失敗則返回0。

    • 通過SetTimer成員函數我們可以看出,處理定時事件可以有兩種方式,一種是通過WM_TIMER消息的消息響應函數,一種是通過回調函數。

    • 如果要啓動多個定時器就多次調用SetTimer成員函數。另外,在不同的CWnd中可以有ID相同的定時器,並不衝突。

  • KillTimer(nIDEvent)函數原型:
    BOOL KillTimer(UINT_PTR nIDEvent)
    {
    	UINT_PTR nIDEvent, //定時器ID
    }
    
  • 多個定時器的例子:
    	void CExample::OnTimer(UINT_PTR nIDEvent)
    	{
    		// TODO: 在此添加消息處理程序代碼和/或調用默認值
    		switch(nIDEvent)
    		{
    			case 1:   //ID爲1的定時器
    				doFuncOne;
    				break;
    			case 2:  //ID爲2的定時器
    				doFuncTwo;
    				break;
    			default:
    				break;
    		}
    		CDialogEx::OnTimer(nIDEvent);
    	}
    
  • *(重點)通過回調函數設置定時器的例子:
    注:回調函數爲全局函數,需要寫在使用它的位置的前面,或者寫在後面然後在使用之前聲明。
    • xx.h無需定義內容
    • xx.cpp:
      • 定義一個顯示當前時間的對話框(寫在cpp#include之後):
        void MyTimer()
        {
        	// TODO: 在此添加消息處理程序代碼和/或調用默認值
        	CTime t = CTime::GetCurrentTime();
        	CString str;
        	str.Format("當前時間:  %04d/%02d/%02d  %02d:%02d:%02d", t.GetYear(), t.GetMonth(), t.GetDay(), t.GetHour(), t.GetMinute(), t.GetSecond());
        	Util::ShowSysMsg(str);
        }
        
      • 定義一個回調函數,調用之前的方法(寫在MyTimer()之後,其中CALLBACK EXPORT爲關鍵字,函數名可自定義,但返回值類型、參數的類型和個數不能改變。)
        void CALLBACK EXPORT TimerProc(HWND hWnd, UINT nMsg, UINT nTimerid, DWORD dwTime)
        {
        	switch (nTimerid)
        	{
        	case 1:
        		MyTimer();
        		break;
        	default:
        		break;
        	}
        }
        
      • 通過SetTimer()調用回調函數
        SetTimer(1, 1000, TimerProc);//1進入case = 1的控制,1000ms,TimerProc爲回調函數名稱,不加()

2.Windows API方式

  • SetTimer函數原型:
    UINT_PTR SetTimer(         
        HWND    
               hWnd,   //窗口句柄
        UINT_PTR    
               nIDEvent,   //定時器ID
       UINT    
              uElapse,   //定時間隔
       TIMERPROC    
             lpTimerFunc   //回調函數
    );
    
    • 參數hWnd爲與定時器關聯的窗口的句柄;參數nIDEvent爲非零的定時器ID,如果hWnd等於NULL,且還不存在ID爲nIDEvent的定時器,那麼nIDEvent參數被忽略,然後生成一個新ID的定時器,而如果hWnd不爲NULL,且hWnd指定的窗口已存在ID爲nIDEvent的定時器,那麼這個已存在的定時器被新定時器所取代。參數uElapse和lpTimerFunc同CWnd::SetTimer函數。

    • 如果調用SetTimer函數時最後一個參數爲NULL,我們需要自己爲WM_TIMER消息添加處理函數,要注意的是,WM_TIMER消息的附加數據wParam爲定時器ID,lParam爲回調函數的指針,如果調用SetTimer時回調函數爲NULL,那麼lParam也爲NULL。

    • 而如果調用SetTimer函數時最後一個參數不爲NULL,我們就需要定義回調函數。回調函數的定義同MFC定時器。

  • 銷燬定時器KillTimer API函數:
    BOOL KillTimer(HWND hWnd,UINT_PTR uIDEvent);
    • 參數hWnd爲與定時器關聯的窗口的句柄,與啓動定時器時SetTimer函數的hWnd參數值相同;參數uIDEvent爲要銷燬的定時器的ID,如果傳遞給SetTimer的參數hWnd有效,則uIDEvent應與傳遞給SetTimer的參數nIDEvent相同,而如果SetTimer的參數hWnd爲NULL,則uIDEvent應爲SetTimer返回的定時器ID。該函數成功則返回TRUE,否則返回FALSE。

3.區別總結

  • CWnd類的SetTimer成員函數只能在CWnd類或其派生類中調用,而API函數SetTimer則沒有這個限制,這是一個很重要的區別。因爲本教程主要是講解MFC編程,所以這裏就先重點講解MFC定時器的用法,關於API函數SetTimer的用法雞啄米會在MFC定時器講解的基礎上進行延伸。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章