CWinApp::OnIdle
virtual BOOL OnIdle( LONG lCount );
返回值:
若是要接收更多的空閒處理時間,則返回非零值;若是不須要更多的空閒時間則返回0。
參數:
lCount 該參數是一個計數值,當應用程序的消息隊列爲空,OnIdle函數被調用時,該計數值就增長1。
每當一條新消息被處理時,該計數值就被複位爲0。你可使用lCount參數來肯定應用程序不處理消息時空閒時間的相對長度。
說明:數據結構
重載CWinApp::OnIdle()時,不要忘記要先調用CWinApp::OnIdle()進行MFC默認處理併發
if (CWinApp::OnIdle(lCount)) return TRUE;
若是忘掉了的話,你會發現一些MFC的UI會出現問題,好比菜單上的選擇狀態沒法更新等問題。框架
對於通常桌面應用程序中比較少重載這個函數。對於像是視頻遊戲這一塊確有很多用處
若是要執行空閒時處理,則重載這個成員函數。當應用程序的消息隊列爲空時,OnIdle就在缺省的消息循環中被調用。
你能夠用重載函數來調用本身的後臺空閒處理任務。
OnIdle應返回0以代表不須要更多的空閒處理時間。
當消息隊列爲空時,OnIdle每被調用一次lCount參數就增長,而每處理一條新消息lCount就被複位爲0。
你能夠根據這個計數值調用不一樣的空閒處理例程。函數
下面總結了空閒循環處理:
一、若是微軟基礎類庫中的消息循環檢查消息隊列並發現沒有未被處理的消息,它就爲應用程序對象調用OnIdle函數,並將lCount參數設爲0。
二、OnIdle執行一些處理,而後返回一個非零值,表示它還須要被調用,以進行進一步處理。
三、消息循環再次檢查消息隊列。若是沒有未處理的消息,則再次調用OnIdle,增長lCount參數。
四、最後,OnIdle結束全部的空閒任務並返回0。
這就告訴消息循環中止調用OnIdle直到在消息隊列中接收到下一條消息爲止,在那時,空閒循環將從新啓動,而參數被設爲0。
由於只有在OnIdle返回以後應用程序才能處理用戶輸入,所以在OnIdle中不該進行較長的任務。工具
注意:
OnIdle的缺省實現更新命令用戶接口對象,如菜單項和工具條等,還實現了內部數據結構的清理。
所以,若是你重載了OnIdle,你必須用重載版本中使用的lCount值來調用CWinApp::OnIdle。
首先調用全部基類的空閒處理(即直到基類的OnIdle返回0)。
若是你須要在基類處理完成以前進行一些工做,則應回顧基類的實現以在本身的工做期間選擇一個合適的lCount值。oop
示例:
下面的兩個例子演示了OnIdle的用法。ui
第一個例子處理兩個空閒任務,用lCount參數來排列這些任務的優先權。
第一個任務優先權較高,一旦可能你就應當執行此任務。第二個任務不十分重要,只有當用戶輸入有一個較長時間的間歇的時候才應執行此任務。
注意其中對基類的OnIdle的調用。
第二個例子管理着一組具備不一樣優先權的空閒任務。spa
BOOL CMyApp::OnIdle(LONG lCount) { BOOL bMore = CWinApp::OnIdle(lCount); if (lCount == 0) { TRACE("App idle for short period of time/n"); bMore = TRUE; } else if (lCount == 10) { TRACE("App idle for longer amount of time/n"); bMore = TRUE; } else if (lCount == 100) { TRACE("App idle for even longer amount of time/n"); bMore = TRUE; } else if (lCount == 1000) { TRACE("App idle for quite a long period of time/n"); // bMore 沒有被設爲TRUE, 不在須要空閒 // 重要:bMore 沒有被設爲 FALSE,由於 CWinApp::OnIdle可能還有其它空閒任務要完成。 } return bMore; // 返回TRUE,只要還有其它空閒任務 }
第二個示例:
// 在這個例子中,有四個空閒循環任務,它們被賦予
// 不一樣的優先權,運行的機會不一樣:
// Task1在空閒時總能運行,要求在框架處理它本身的空閒循環任務時沒有消息在等候。(lCount爲0或1)
// Task2 僅當Task1以及運行時才能運行,要求當Task1運行時沒有消息在等候。
// Task3和Task4僅當Task1和Task2都運行以後才能運行,
// 而且在此期間沒有消息在等候。若是Task3可以運行,
// 則Task4老是在Task3以後當即運行。
BOOL CMyApp::OnIdle(LONG lCount)
{
// 在這個例子中,像多數應用程序同樣,你應該讓基類
// 的CWinApp::OnIdle在你試圖進行任何附加的空閒循環
// 過程以前完成它的處理。
if (CWinApp::OnIdle(lCount)) return TRUE;
// 基類的CWinApp::OnIdle爲lCount保留0和1給框架本身的
// 空閒處理使用。若是你但願與框架平等地共享空閒處理
// 時間,則應替換上面的if語句,直接調用CWinApp::OnIdle,
// 而後爲lCount的值0和/或1加入一個case語句。首先應當研
// 究基類的實現以理解你的空閒循環任務將會如何與框架的
// 空閒循環處理競爭。
switch (lCount)
{
case 2:
Task1();
return TRUE; // 下一次給 Task2 一個機會
case 3:
Task2();
return TRUE; // 下一次給Task3和Task4一個機會
case 4:
Task3();
Task4();
return FALSE; // 再次回到空閒循環任務
}
return FALSE;
}
///注意
在VC基於對話框程序中,彷佛不能使用OnIdle。從網上查了一下,能夠用WM_KICKIDLE消息實現相同功能。WM_KICKIDLE消息響應須要本身手動添加代碼。下面是步驟:
1.MyDlg.cpp文件添加包含:
#include <afxpriv.h>
2.MyDlg.h文件添加聲明
afx_msg LRESULT OnKickIdle(WPARAM wParam, LPARAM lParam);
3.MyDlg.cpp文件添加消息映射:
ON_MESSAGE(WM_KICKIDLE,OnKickIdle)
4.MyDlg.cpp添加函數的實現:
LRESULT CMyDlg::OnKickIdle(WPARAM wParam, LPARAM lParam)
{
//------TODO--------------------------------code
return 0;
}視頻
當沒有任何 Windows 消息正在被處理時,框架調用 CWinApp 的成員函數 OnIdle(如「MFC 庫參考」中所述)。
重寫 OnIdle 以執行後臺任務。默認版本更新用戶界面對象(如工具欄按鈕)的狀態,並對框架在操做期間建立的臨時對象執行清理工做。下面闡釋了在隊列中沒有任何消息時消息循環調用 OnIdle 的方式。
int CWinThread::Run() { ....... for(;;) { while (bIdle && //bIdle控制上圖的是否有其餘空閒任務 !::PeekMessage(&m_msgCur,NULL,NULL,PM_NOREMOVE)) { if (!OnIdle(lIdleCount++)) { bIdle = FALSE; } } ......//msg loop } }