1. 程式人生 > >【轉】MFC OnIdle的詳細說明

【轉】MFC OnIdle的詳細說明

理解 輸入 成員函數 並且 重載函數 未處理 target spa 命令

轉載出處:http://blog.csdn.net/tsing_best/article/details/25055707

CWinApp::OnIdle
virtual BOOL OnIdle( LONG lCount );
返回值
  如果要接收更多的空閑處理時間,則返回非零值;如果不需要更多的空閑時間則返回0。
參數
  lCount 該參數是一個計數值,當應用程序的消息隊列為空,OnIdle函數被調用時,該計數值就增加1。
  每當一條新消息被處理時,該計數值就被復位為0。你可以使用lCount參數來確定應用程序不處理消息時空閑時間的相對長度。
說明
  如果要執行空閑時處理,則重載這個成員函數。當應用程序的消息隊列為空時,OnIdle就在缺省的消息循環中被調用。


  你可以用重載函數來調用自己的後臺空閑處理任務。
  OnIdle應返回0以表明不需要更多的空閑處理時間。
  當消息隊列為空時,OnIdle每被調用一次lCount參數就增加,而每處理一條新消息lCount就被復位為0。
  你可以根據這個計數值調用不同的空閑處理例程。

  下面總結了空閑循環處理:
  1、如果微軟基礎類庫中的消息循環檢查消息隊列並發現沒有未被處理的消息,它就為應用程序對象調用OnIdle函數,並將lCount參數設為0。
  2、OnIdle執行一些處理,然後返回一個非零值,表示它還需要被調用,以進行進一步處理。
  3、消息循環再次檢查消息隊列。如果沒有未處理的消息,則再次調用OnIdle,增加lCount參數。


  4、最後,OnIdle結束所有的空閑任務並返回0。
  這就告訴消息循環停止調用OnIdle直到在消息隊列中接收到下一條消息為止,在那時,空閑循環將重新啟動,而參數被設為0。
因為只有在OnIdle返回之後應用程序才能處理用戶輸入,因此在OnIdle中不應進行較長的任務。

註意
  OnIdle的缺省實現更新命令用戶接口對象,如菜單項和工具條等,還實現了內部數據結構的清理。
  因此,如果你重載了OnIdle,你必須用重載版本中使用的lCount值來調用CWinApp::OnIdle。
  首先調用所有基類的空閑處理(即直到基類的OnIdle返回0)。
  如果你需要在基類處理完成之前進行一些工作,則應回顧基類的實現以在自己的工作期間選擇一個合適的lCount值。

示例
  下面的兩個例子演示了OnIdle的用法。

  第一個例子處理兩個空閑任務,用lCount參數來排列這些任務的優先權。
  第一個任務優先權較高,一旦可能你就應當執行此任務。第二個任務不十分重要,只有當用戶輸入有一個較長時間的間歇的時候才應執行此任務。
  註意其中對基類的OnIdle的調用。
  第二個例子管理著一組具有不同優先權的空閑任務。

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--------------------------------

  return 0;
}

【轉】MFC OnIdle的詳細說明