Figure 2   CWaitDialog's Public Member Functions


CWaitDialog (BOOL* pFlag, LPCTSTR pszCaption = NULL, 
             LPCTSTR pszText = NULL)
Description
Constructs a CWaitDialog object and dialog and displays the dialog on the screen.
Parameters
pFlag Pointer to a BOOL flag that the dialog will set to FALSE when the Cancel button is clicked.
pszCaption Pointer to a text string specifying the dialog caption. If this parameter is NULL, the caption defaults to "Working."
pszText Pointer to a text string specifying the message text that appears above the dialog's progress control. If this parameter is NULL, the message text defaults to "Click Cancel to cancel the operation."

void SetPercentComplete (int nPercent)
Description
Sets the dialog's progress bar to reflect the status of an ongoing operation.
Parameters
nPercent An integer from zero to 100 specifying percent complete.

void SetMessageText (LPCTSTR pszText)
Description
Changes the message text displayed in the body of the dialog.
Parameters
pszText Pointer to a text string specifying the message text that appears above the dialog's progress control.

BOOL Pump ()
Description
Retrieves and dispatches messages waiting in the application's message queue. Call this function periodically while a CWaitDialog is displayed to allow the dialog to respond to clicks of its Cancel button. The more often Pump is called, the more responsive the application will be.
Return Value
TRUE if it's okay for processing to continue, or FALSE if the message handler that called Pump should return immediately. A FALSE return means there's a WM_QUIT message waiting to be retrieved from the message queue.

void Close ()
Description
Closes the dialog. If a CWaitDialog object goes out of scope before this function is called, the dialog is closed automatically.


Figure 3   CWaitDialog

Demo.rc


 //***************************************************************************
 //
 //  Demo.rc
 //
 //***************************************************************************
 
 #include <afxres.h>
 #include "WaitDlg.rc"
 
 // Other resources go here...
Demo.h

 //***********************************************************************
 //
 //  Demo.h
 //
 //***********************************************************************
 
 class CMyApp : public CWinApp
 {
 public:
     virtual BOOL InitInstance ();
 };
 
 class CMainWindow : public CFrameWnd
 {
 public:
     CMainWindow ();
 
 protected:
     void DrawRandomEllipse (CDC*, CRect&);
 
     afx_msg void OnLButtonDown (UINT, CPoint);
     DECLARE_MESSAGE_MAP ()
 };
Demo.cpp

 //***********************************************************************
 //
 //  Demo.cpp
 //
 //***********************************************************************
 
 #include <afxwin.h>
 #include <stdlib.h>
 #include "WaitDlg.h"
 #include "Demo.h"
 
 CMyApp myApp;
 
 /////////////////////////////////////////////////////////////////////////
 // CMyApp member functions
 
 BOOL CMyApp::InitInstance ()
 {
     m_pMainWnd = new CMainWindow;
     m_pMainWnd->ShowWindow (m_nCmdShow);
     m_pMainWnd->UpdateWindow ();
     return TRUE;
 }
 
 /////////////////////////////////////////////////////////////////////////
 // CMainWindow message map and member functions
 
 BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
     ON_WM_LBUTTONDOWN ()
 END_MESSAGE_MAP ()
 
 CMainWindow::CMainWindow ()
 {
     Create (NULL, "CWaitDialog Demo");
 }
 
 void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
 {
     CRect rect;
     GetClientRect (&rect);
     CClientDC dc (this);
 
     //
     // Display a cancel dialog.
     //
     BOOL bContinue = TRUE;
     CWaitDialog dlg (&bContinue);
 
     int nCount = 0;
     int nPercentComplete = 0;
 
     //
     // Draw ellipses until Cancel is clicked or we've reached our
     // quota of ellipses.
     //
     while (bContinue) {
         DrawRandomEllipse (&dc, rect);
         if (++nCount >= 200) {
             nCount = 0;
             nPercentComplete += 2;
             dlg.SetPercentComplete (nPercentComplete);
 
             if (nPercentComplete == 80)
                 dlg.SetMessageText ("Almost done!");
 
             if (nPercentComplete == 100)
                 break;
         }
         dlg.Pump ();
     }
 
 }
 
 void CMainWindow::DrawRandomEllipse (CDC* pDC, CRect& rect)
 {
     int x1 = rand () % rect.right;
     int x2 = rand () % rect.right;
     int y1 = rand () % rect.bottom;
     int y2 = rand () % rect.bottom;
 
     CRect rcEllipse (x1, y1, x2, y2);
     rcEllipse.NormalizeRect ();
 
     CBrush brush (RGB (rand () % 255, rand () % 255, rand () % 255));
     CBrush* pOldBrush = pDC->SelectObject (&brush);
 
     pDC->Ellipse (&rcEllipse);
 
     pDC->SelectObject (pOldBrush);
 }
WaitDlg.h

 //***************************************************************************
 //
 //  WaitDlg.h
 //
 //***************************************************************************
 
 class CWaitDialog : public CDialog
 {
 protected:
     BOOL* m_pFlag;
 
 public:
     CWaitDialog (BOOL*, LPCTSTR = NULL, LPCTSTR = NULL);
     virtual ~CWaitDialog ();
 
     virtual void OnCancel ();
 
     BOOL Pump ();
     void SetPercentComplete (int);
     void SetMessageText (LPCTSTR);
     void Close ();
 };
WaitDlg.cpp

 //***************************************************************************
 //
 //  WaitDlg.cpp
 //
 //***************************************************************************
 
 #include <afxwin.h>
 #include <afxcmn.h>
 #include "WaitRsc.h"
 #include "WaitDlg.h"
 
 /////////////////////////////////////////////////////////////////////////////
 // CWaitDialog class implementation
 
 CWaitDialog::CWaitDialog (BOOL* pFlag, LPCTSTR pszCaption, LPCTSTR pszText) :
     CDialog ()
 {
     m_pFlag = pFlag;
 
     //
     // Disable the main window and create the dialog.
     //
     AfxGetMainWnd ()->EnableWindow (FALSE);
     Create (IDD_WAITDIALOG);
 
     //
     // Initialize the dialog caption and the static text control.
     //
     SetWindowText ((pszCaption == NULL) ? "Working" : pszCaption);
 
     CStatic* pCtrl = (CStatic*) GetDlgItem (IDC_MSGCTRL);
     pCtrl->SetWindowText ((pszText == NULL) ? "Click Cancel to cancel " \
         "the operation" : pszText); 
 
     //
     // Display the dialog.
     //
     ShowWindow (SW_SHOW);
 }
 
 CWaitDialog::~CWaitDialog ()
 {
     Close ();
 }
 
 void CWaitDialog::OnCancel ()
 {
     *m_pFlag = FALSE;
     Close ();
 }
 
 BOOL CWaitDialog::Pump ()
 {
     MSG msg;
 
     //
     // Retrieve and dispatch any waiting messages.
     //
     while (::PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) {
         if (!AfxGetApp ()->PumpMessage ()) {
             ::PostQuitMessage (0);
             return FALSE;
         }
     }
 
     //
     // Simulate the framework's idle processing mechanism.
     //
     LONG lIdle = 0;
     while (AfxGetApp ()->OnIdle (lIdle++));
     return TRUE;
 }
 
 void CWaitDialog::SetPercentComplete (int nPercent)
 {
if (::IsWindow (m_hWnd)) {
        if (nPercent < 0)
            nPercent = 0;
        else if (nPercent > 100)
            nPercent = 100;

        CProgressCtrl* pCtrl = (CProgressCtrl*) GetDlgItem (IDC_PROGRESSCTRL);
        pCtrl->SetPos (nPercent);
    }
}

void CWaitDialog::SetMessageText (LPCTSTR pszText)
{
    if (::IsWindow (m_hWnd)) {
        CStatic* pCtrl = (CStatic*) GetDlgItem (IDC_MSGCTRL);
        pCtrl->SetWindowText (pszText);
    }
}

void CWaitDialog::Close ()
{
    if (::IsWindow (m_hWnd)) {
        AfxGetMainWnd ()->EnableWindow (TRUE);
        DestroyWindow ();
    }
}
WaitRsc.h

//***************************************************************************
//
//  WaitRsc.h
//
//***************************************************************************

#define IDD_WAITDIALOG      100
#define IDC_PROGRESSCTRL    200
#define IDC_MSGCTRL         300