当没有任何 Windows 消息正在被处理时,框架调用 的成员函数 (如“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中不应进行较长的任务。