Updating a Gauge and Detecting a User Interrupt (C++ 4.0 and later)

Take the following steps to update a gauge during processing and detect a user interrupt:

1. Start with the project that you created in Loading and Displaying an Image.

2. Go to the Project WorkSpace and click the ResourceView tab.

3. Double-click Dialog and double-click IDD_TUTOR_DIALOG to bring up the application's dialog box.

4. image\btncmd.gif Add a new button under the Cancel button. To do this, select the button control on the Controls toolbar. Then, click and drag to position the button on the dialog box.

5. Add another button under the previously added button.

6. Double-click the first button and change IDC_BUTTON1 to IDC_MEDIAN. Also, set the caption to Do &Median.

7. Double-click the second button and change IDC_BUTTON2 to IDC_QUIT. Also, set the caption to &Quit.

8. To build a gauge, select the Progress control on the Controls toolbar. (If you do not have a Progress control, you can use any control that has a rectangular shape and a border.) Put the gauge at the top of the dialog box to keep it away from the image.

9. Double-click on the gauge and change the ID from IDC_PROGRESS1 to IDC_GAUGE.

10. Close all the windows until you reach the project window, answering yes when asked whether to save the changes.

11. Press Ctrl-W to go to the MFC Class Wizard; then do the following:

a. In the Class name combo box, select CTutorDlg.

b. In the Object IDs list box, select IDC_MEDIAN.

c. In the Messages list box, select BN_CLICKED.

d. Click the Add function button. Choose OK for the default function name (OnMedian).

e. Click the Edit Code button to start entering the code.

12. Enter new code as follows:

void CTutorDlg::OnMedian() 
{
  // TODO: Add your control notification handler code here
  // Enable the ProgressStatus event
  m_Lead1.SetEnableProgressEvent( TRUE );
  // Initialize the indicators
  fEscape = FALSE; // The user does not want to quit
  fInProc = TRUE; // Processing is taking place
  // Perform a relatively slow median filter
  m_Lead1.Median(4); 
  // Clean up
  fInProc = FALSE; //  Processing is no longer taking place
  m_Lead1.ForceRepaint();
  // reset the gauge
  GetDlgItem(IDC_GAUGE)->InvalidateRect(NULL, TRUE);
}

13. Press Ctrl-W to go to the MFC Class Wizard; then do the following:

a. In the Class name combo box, select CTutorDlg.

b. In the Object IDs list box, select IDC_QUIT.

c. In the Messages list box, select BN_CLICKED.

d. Click the Add function button. Choose OK for the default function name (OnQuit).

e. Click the Edit Code button to start entering the code.

14. Enter new code as follows:

void CTutorDlg::OnQuit() 
{
  // TODO: Add your control notification handler code here
  fEscape = TRUE; // The user wants to quit

  // Set the gauge back to the beginning
  GetDlgItem(IDC_GAUGE)->InvalidateRect(NULL, TRUE);
}

15. Edit the TUTORDLG.H file and change the definition of CTutorDlg : CDialog by inserting the following lines after DECLARE_MESSAGE_MAP:

BOOL    fInProc;
BOOL    fEscape;

16. Press Ctrl-W to go to the MFC Class Wizard; then do the following:

a. In the Class name combo box, select CTutorDlg.

b. In the Object IDs list box, select IDC_LEAD1.

c. In the Messages list box, select ProgressStatus.

d. Click the Add function button. Choose OK for the default function name (OnProgressStatusLead1).

e. Click the Edit Code button to start entering the code.

17. Enter new code as follows:

void CTutorDlg::OnProgressStatusLead1(short iPercent)
{
  MSG msg;
  // are there any messages in the queue (like a button being pressed) ?
  while( PeekMessage(&msg,NULL, 0, 0, PM_REMOVE) )
  {
    TranslateMessage( &msg );      /* Translates virtual key codes.  */
    DispatchMessage( &msg );       /* Dispatches message to window.  */
  }
  if( !fEscape ) // Look for the Click on the Quit button
  {
    CWnd *pwndGauge = GetDlgItem( IDC_GAUGE );
    RECT rcGauge;
    pwndGauge->GetClientRect( &rcGauge );
    // Update the gauge
    short LineLength = (rcGauge.right-rcGauge.left) * iPercent / 100; 
    CDC *pdc = pwndGauge->GetDC();
    CPen hpen( PS_SOLID, rcGauge.bottom - rcGauge.top, RGB(0,0,0) ); // black pen
    CPen *pOldPen = pdc->SelectObject(&hpen);

    pdc->MoveTo( rcGauge.left, (rcGauge.top + rcGauge.bottom) / 2 );
    pdc->LineTo( rcGauge.left + LineLength, (rcGauge.top + rcGauge.bottom) / 2 );
    pdc->SelectObject(pOldPen);
  }
  else
    m_Lead1.SetEnableProgressEvent(FALSE); // Cancel the task
}

18. Continue with the remaining steps to prevent the user from quitting while a process is still going. This requires additional checks in the handling of the OK and Cancel buttons.

19. Press Ctrl-W to go to the MFC Class Wizard; then do the following:

a. In the Class name combo box, select CTutorDlg.

b. In the Object IDs list box, select IDCANCEL.

c. In the Messages list box, select BN_CLICKED.

d. Click the Add function button. Choose OK for the default function name (OnCancel).

e. Click the Edit Code button to start entering the code.

20. Enter new code as follows:

void CTutorDlg::OnCancel() 
{
  // TODO: Add extra cleanup here
  if( !fInProc )
    CDialog::OnCancel();
}

21. Press Ctrl-W to go to the MFC Class Wizard; then do the following:

a. In the Class name combo box, select CTutorDlg.

b. In the Object IDs list box, select IDOK.

c. In the Messages list box, select BN_CLICKED.

d. Click the Add function button. Choose OK for the default function name (OnOK).

e. Click the Edit Code button to start entering the code.

22. Enter new code as follows:

void CTutorDlg::OnOK() 
{
  // TODO: Add extra validation here
  if( !fInProc )
    CDialog::OnOK();
}

23. Insert the following line in the TUTORDLG.CPP file at the end of CTutorDlg::OnInitDialog, just before the return statement:

fInProc = FALSE;

24. Rebuild the application and run the program.