Idle-time Processing


Click here to change the theme.

The default MFC processing for CWinApp::OnIdle is to return TRUE if lCount is zero and return FALSE otherwise. This means that it gets called when the value is zero or one but after that it is not called again until after there is another message. Try overriding CWinApp::OnIdle and use something such as the following:

BOOL COnIdleApp::OnIdle(LONG lCount) {
TRACE1("%i OnIdle\n", lCount);
if (lCount == 0)
	return CWinApp::OnIdle(lCount);
if (lCount == 1) {
	CWinApp::OnIdle(lCount);
	return 1;
	}
if (lCount < 9)
	return 1;
return 0;
}

Unless a modal dialog is being shown, you should see the count go from 0 to 9 many times but it will not go above 9.

So a possible practical use of OnIdle could be:

BOOL CMyApp::OnIdle(LONG lCount) {
if (CWinApp::OnIdle(lCount)) // MFC have more work?
	return 1; // Give MFC a chance to finish first
return DoIdleWork(); // Do our application's idle processing.
}

References

The following is not a complete list of material about idle processing but it is some.

  • Idle Loop Processing does not describe the OnIdle solution much but it does describe a couple of alternatives that use PeekMessage in a message loop.
  • Use the WM_KICKIDLE Message for Modal Dialogs

    The WM_IDLE message will not be processed for modal dialogs; that is, when a DoModal is executing. There is, however, a MFC "private" message that is somewhat documented. It is the the WM_KICKIDLE message.  You must add an entry to the message map for the dialog class header. Add it outside of the ClassWizard-managed portion, as in the following:

    // Generated message map functions
    //{{AFX_MSG(CDialogsDlg)
    //}}AFX_MSG
    afx_msg LRESULT OnKickIdle(WPARAM, LPARAM);
    DECLARE_MESSAGE_MAP()

    You must also include afxpriv.h somewhere; either in you dialog's ".cpp" file or in your "stdafx.h" file. You must also add an entry to the message map for the dialog class implementation too. Add it outside of the ClassWizard-managed portion, as in the following:

    BEGIN_MESSAGE_MAP(CDialogsDlg, CDialog)
    //{{AFX_MSG_MAP(CDialogsDlg)
    //}}AFX_MSG_MAP
    ON_MESSAGE(WM_KICKIDLE, OnKickIdle)
    END_MESSAGE_MAP()

    Then you can handle the WM_KICKIDLE message in a manner similar to the handling of the WM_IDLE message, as in the following: 

    LRESULT CDialogsDlg::OnKickIdle(WPARAM, LPARAM lCount) {
    // Do processing similar to processing for the WM_IDLE message
    }

    Except LPARAM is the idle count corresponding to the idle count for WM_IDLE. Return TRUE/FALSE to continue/discontinue idle processing.

    References

    The following is about everything that Microsoft has to say about WM_KICKIDLE. The sample code above is a simpler version of one of these.

    • CWnd::RunModalLoop
    • MSJ June 1996 C/C++ Q&A (The last question asks about idle processing in modal dialogs and the answer is to the WM_KICKIDLE message.)
    • MSJ July 1997 C/C++ Q&A (The last question asks how to change the tab order of controls in a dialog box and the answer includes a description of the WM_KICKIDLE message.)