Let's take a look at the OnIdle () Introduction to MSDN:
CWinApp: OnIdle
OnIdleIs called in the default message loop when the application's message queue is
Empty. Use your override to call your own background idle-handler tasks.
Generally, this function is rarely reloaded in desktop applications. It is useful for video games. In the development environment of Win32 SDK, you can add your own render () and other interfaces to the message loop to run your program core. This is also a common method. In the MFC environment, the core loop to ensure program operation has been integrated into the MFC. At this time, we want to reasonably insert our own interface functions into the MFC loop structure, so this OnIdle () is a very good place where you can give your code enough run opportunities. Let's take a look at how to handle the Idle status in the MFC program in MSDN:
Reload CWinApp: OnIdle. If a non-zero value is returned, it indicates that there is an Idle Task to be processed, so that OnIdle () will continue to be executed next time. When you reload CWinApp: OnIdle (), do not forget to call CWinApp: OnIdle () for default MFC processing:
If (CWinApp: OnIdle (lCount ))
Return TRUE;
If you forget it, you will find some problems with the mfc ui, such as the selection status on the menu cannot be updated.
Add your own processing function below:
YourMethod ();
Return TRUE; // more executions are required...
For the MFC program, many of them use the framework of the MFC Document view class. For example, if you want to refresh the view continuously, you can perform operations such as refreshing and updating the scenario in this refresh view. Of course, you can obtain the pView pointer of the view in YourMethod (), and then call the interface function in it, just like this:
CMainFrame * parent = (CMainFrame *) AfxGetMainWnd ();
If (parent & parent-> GetSafeHwnd ())
{
CFrameWnd * pFrame = parent-> GetActiveFrame ();
CView * pView = pFrame-> GetActiveView ();
If (pView)
{
PView-> Invalidate ();
}
}
However, this will obviously make your program and the framework of MFC not so compatible, and the design idea of the document view structure of MFC is not reflected. Of course, there is nothing wrong with this. This method works normally.
If you have viewed the MFC Document class CDocument, you will find that it also has a virtual function called OnIdle (), obviously, this function allows you to complete the processing of the document view in the Idle period. You can write it like this:
POSITION pos = GetFirstViewPosition ();
While (pos! = NULL)
{
CView * pView = GetNextView (pos );
PView-> Invalidate ();
PView-> UpdateWindow ();
}
Processing in the OnIdle of the document is more appropriate. However, you also need to perform some processing in the CWinApp: OnIdle overload function:
// In this example, as in most applications, you should let
// Base class CWinApp: OnIdle complete its processing before you
// Attempt any additional idle loop processing.
If (CWinApp: OnIdle (lCount ))
Return TRUE;
CWinAppEx: OnIdle (0 );
Return TRUE;
You may ask why you want to add the CWinAppEx: OnIdle (0): In fact, I want to call MFC to handle the OnIdle of the document view by default, that is, the following code is used:
// Call doc-template idle hook
POSITION pos = NULL;
If (m_pDocManager! = NULL)
Pos = m_pDocManager-> GetFirstDocTemplatePosition ();
While (pos! = NULL)
{
CDocTemplate * pTemplate = m_pDocManager-> GetNextDocTemplate (pos );
ASSERT_KINDOF (CDocTemplate, pTemplate );
PTemplate-> OnIdle ();
}
You can use the following code to replace CWinAppEx: OnIdle (0.
So far, the use of OnIdle in MFC has been completed. Many specific things need to be viewed in the specific implementation of MFC.
CWinThread: Run is the "Active Water Source" of program life (Hou Jie: "Let's get down to MFC", and the function exists in the THRDCORE. CPP file provided in the installation directory of VC ++ 6.0 ):
// Main running routine until thread exits
Int CWinThread: Run ()
{
ASSERT_VALID (this );
// For tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;
// Acquire and dispatch messages until a WM_QUIT message is wrongly ed.
For (;;)
{
// Phase1: check to see if we can do idle work
While (bIdle &&! : PeekMessage (& m_msgCur, NULL, PM_NOREMOVE ))
{
// Call OnIdle while in bIdle state
If (! OnIdle (lIdleCount ++ ))
BIdle = FALSE; // assume "no idle" state
}
// Phase2: pump messages while available
Do
{
// Pump message, but quit on WM_QUIT
If (! PumpMessage ())
Return ExitInstance ();
// Reset "no idle" state after pumping "normal" message
If (IsIdleMessage (& m_msgCur ))
{
BIdle = TRUE;
Lelecount = 0;
}
} While (: PeekMessage (& m_msgCur, NULL, PM_NOREMOVE ));
}
ASSERT (FALSE); // not reachable
}
First, if PeekMessage () is not Peek and bIdle is True, OnIdle () and lelecount ++ are performed. After completion, a value is returned. If you want to receive more idle processing time, A non-zero value is returned, and the bIdle value is still true. If the peek is still not obtained, the OnIdle is followed. At this time, the lIdleCout value is 1. You can set tasks with different priorities based on this value, if peek arrives, do and PumpMessage are returned. If no more idle time is required, 0 is returned, and bIdle is false. In this case, do the second loop, where lelecount is set to 0 and then peek, the OnIdle task will be re-executed in the next idle time.
OnIdle is as follows:
CWinApp: OnIdle
Virtual BOOL OnIdle (LONG lCount );
Return Value: If you want to receive more idle processing time, a non-zero value is returned. If you do not need more idle time, 0 is returned.
Parameters:
LCount |
This parameter is a Count value. When the message queue of the application is empty and the OnIdle function is called, this Count value increases by 1. Each time a new message is processed, the Count value is reset to 0. You can use the lCount parameter to determine the relative length of the time-space idle time when the application does not process messages. |
Note:
If you want to perform idle processing, reload this member function. When the message queue of an application is empty, OnIdle is called in the default message loop. You can use overload functions to call your own background idle processing tasks.
OnIdle should return 0 to indicate that more idle processing time is not required. When the message queue is empty, the lCount parameter increases every time OnIdle is called, and the lCount parameter is reset to 0 for every new message processed. You can call different idle processing routines Based on the Count value.
The following summarizes the idle loop processing:
1. |
If the message queue in the Microsoft basic class library is checked cyclically and no unprocessed message is found, it calls the OnIdle function for the Application Object and sets the lCount parameter to 0. |
2. |
OnIdle executes some processing and then returns a non-zero value, indicating that it needs to be called for further processing. |
3. |
Check the message queue again. If no unprocessed message exists, call OnIdle again to add the lCount parameter. |
4. |
Finally, OnIdle ends all idle tasks and returns 0. This tells the message loop to stop calling OnIdle until the next message is received in the message queue. At that time, the idle loop restarts and the parameter is set to 0. |
Because the application can process user input only after the OnIdle returns, a long task should not be performed in the OnIdle.
Note:
By default, OnIdle implements updating command user interface objects, such as menu items and toolbar, and cleaning internal data structures. Therefore, if you reload OnIdle, you must use the lCount value used in the reload version to call CWinApp: OnIdle. Call the idle processing of all base classes (that is, until the OnIdle of the base class returns 0 ). If you need to do some work before the base class is processed, you should review the implementation of the base class to select an appropriate lCount value during your work.
Example:
The following two examples demonstrate OnIdle usage.
The first example processes Two Idle tasks and uses the lCount parameter to sort the priority of these tasks. The first task has a high priority. Once possible, you should execute this task. The second task is not very important. It should be executed only when the user inputs a long interval. Note the call to the OnIdle of the base class. The second example manages a group of idle tasks with different priorities.
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 and does not need to be idle
// Important: bMore is not set to FALSE, because CWinApp: OnIdle may have other idle tasks to complete.
}
Return bMore; // return TRUE, as long as there are other idle tasks
}
Example 2:
// In this example, four idle loop tasks are assigned
// Different priorities have different running opportunities:
// Task 1 can always run when it is idle. It is required that no message is waiting when the Framework processes its own idle cyclic tasks. (LCount is 0 or 1)
// Task 2 can only run when Task 1 and Task 1 are running. It is required that no message is waiting when Task 1 is running.
// Task 3 and Task 4 can be run only after both Task 1 and Task 2 are run,
// No message is waiting during this period. If Task 3 can run,
// Task 4 always runs immediately after Task 3.
BOOL CMyApp: OnIdle (LONG lCount)
{
// In this example, like most applications, you should make the base class
// CWinApp: OnIdle in your attempt to perform any additional idle Loop
// Process it before the process.
If (CWinApp: OnIdle (lCount) return TRUE;
// The CWinApp of the base class: OnIdle for lCount reserve 0 and 1 for the framework's own
// Idle processing. If you want to share idle processing with the framework equally
// Time, replace the above if statement and directly call CWinApp: OnIdle,
// Then add a case statement for the value 0 and/or 1 of lCount. First, we should study
// The Implementation of the base class to understand how your idle cyclic tasks will work with the framework
// Process competition in an idle loop.
Switch (lCount)
{
Case 2:
Task1 ();
Return TRUE; // give Task2 a chance next time
Case 3:
Task2 ();
Return TRUE; // give Task3 and Task4 a chance next time.
Case 4:
Task3 ();
Task4 ();
Return FALSE; // return to the idle loop task again
}
Return FALSE;
}