當沒有任何 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
}
}
如果自己的程序想處理idle time,只要改寫CWinApp派生類的OnIdle函數即可:
vitual BOOL OnIdel(LONG lCount);(返回False表示不再需要空閒處理,但下一次有消息來,處理完消息後,bIdle又置爲True,又可以進行空閒處理)
lCount表示從上次有消息進來,到現在,OnIdle已經被調用了多少次,如上面的循環,沒調一次OnIdle,lCount累加一次,
知道有消息到來時,lCount被重置爲0.(WM_SYTEMTIMER和WM_PAINT消息不會使lCount置爲0).
以下兩個程序在不同的空閒時間做不同的處理:
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 is not set to TRUE, no longer need idle
// IMPORTANT: bMore is not set to FALSE since CWinApp::OnIdle may
// have more idle tasks to complete.
}
return bMore;
// return TRUE as long as there is any more idle tasks
}
// In this example, four idle loop tasks are given various
// opportunities to run:
// Task1 is always given a chance to run during idle time, provided
// that no message has queued up while the framework was processing
// its own idle loop tasks (at lCount levels 0 and 1).
// Task2 is given a chance to run only if Task1 has already run,
// provided that no message has queued up while Task1 was running.
// Task3 and Task4 are given a chance to run only if both Task1 and
// Task2 have already run, and no message has queued up in the mean
// time. If Task3 gets its chance to run, then Task4 always gets
// a chance to run immediately after Task3.
BOOL CMyApp::OnIdle(LONG lCount)
{
// In this example, as in most applications, you should let the
// base class CWinApp::OnIdle complete its processing before you
// attempt any additional idle loop processing.
if (CWinApp::OnIdle(lCount))
return TRUE;
// The base class CWinApp::OnIdle reserves the lCount values 0
// and 1 for the framework's own idle processing. If you wish to
// share idle processing time at a peer level with the framework,
// then replace the above if-statement with a straight call to
// CWinApp::OnIdle; and then add a case statement for lCount value
// 0 and/or 1. Study the base class implementation first to
// understand how your idle loop tasks will compete with the
// framework's idle loop processing.
switch (lCount)
{
case 2:
Task1();
return TRUE; // next time give Task2 a chance
case 3:
Task2();
return TRUE; // next time give Task3 and Task4 a chance
case 4:
Task3();
Task4();
return FALSE; // cycle through the idle loop tasks again
}
return FALSE;
}
因爲只有在OnIdle返回之後應用程序才能處理用戶輸入,因此在OnIdle中不應進行較長的任務。