Filter Library Camera Interface Physics

ProgressDlg.cpp

00001 /*
00002  * ProgressDlg.cpp - progress dialog for computational intensive operations.
00003  *
00004  * This file is part of the Camera Filter Library.
00005  * Computer Aided Measurement Environment for Realtime Atomic imaging (Camera)
00006  *
00007  * Copyright (C) 2004-2005, Leiden Probe Microscopy.
00008  * Copyright (C) 2004-2005, Universiteit Leiden.
00009  *
00010  * Authors: M. Seynen (original), Martin J. Moene (complete rewrite)
00011  *
00012  * $Id: ProgressDlg.cpp 252 2005-09-19 14:19:24Z moene $
00013  */
00014 
00015 /*
00016  * included files:
00017  */
00018 
00019 #include "stdafx.h"                     // for common (pre-compiled) headers
00020 //#include <cfl/stdafx.h>                 // for common (pre-compiled) headers
00021 #include <cfl/resource.h>               // for dialog resources
00022 #include <cfl/ProgressDlg.h>            // this class
00023 
00024 #ifdef _DEBUG
00025 #define new DEBUG_NEW
00026 #undef THIS_FILE
00027 static char THIS_FILE[] = __FILE__;
00028 #endif
00029 
00030 /**
00031  * our timer event.
00032  */
00033 const int CProgressDlg::c_nTimerIDEvent = 0x123;
00034 
00035 /**
00036  * (default) constructor.
00037  */
00038 CProgressDlg::CProgressDlg( CWnd* pParent /*= NULL */ ) :
00039    CDialog( CProgressDlg::IDD, pParent ),
00040    m_pThread         ( NULL  ),         // the computation thread
00041 //   m_wndProgress;                     // advanced progress bar from Rogue Wave Objective Toolkit
00042    m_bInitialized    ( FALSE ),         // set flag after successful OnInitDialog()
00043    m_bCancel         ( FALSE ),         // Cancel-button or Esc-key pressed flag
00044    m_bResumed        ( FALSE ),         // computation thread has been resumed flag
00045    m_nLowerPosition  (   0   ),         // progress bar lower position
00046    m_nUpperPosition  (   1   ),         // progress bar upper position
00047    m_nCurrentPosition(   0   )          // progress bar current position
00048 {
00049 //   Q_LOG( _T("CProgressDlg::CProgressDlg()") );
00050 
00051    //{{AFX_DATA_INIT(CProgressDlg)
00052    //}}AFX_DATA_INIT
00053 }
00054 
00055 /**
00056  * destructor.
00057  */
00058 CProgressDlg::~CProgressDlg()
00059 {
00060 //   Q_LOG( _T("CProgressDlg::~CProgressDlg()") );
00061 }
00062 
00063 /**
00064  * the thread has informed us that it has been resumed.
00065  */
00066 BOOL CProgressDlg::IsResumed()
00067 {
00068    /*
00069     * simple boolean: we don't use the critical section.
00070     */
00071    return m_bResumed;
00072 }
00073 
00074 /**
00075  * Cancel-button or Escape-key pressed (window close message).
00076  */
00077 BOOL CProgressDlg::IsCanceling()
00078 {
00079    /*
00080     * simple boolean: we don't use the critical section.
00081     */
00082    return m_bCancel;
00083 }
00084 
00085 /**
00086  * Cancel-button or Esc-key pressed; alias for IsCanceling().
00087  */
00088 BOOL CProgressDlg::StopRequested()
00089 {
00090    return IsCanceling();
00091 }
00092 
00093 /**
00094  * set resumed flag.
00095  */
00096 void CProgressDlg::SetResumed()
00097 {
00098    /*
00099     * "produce":
00100     * simple boolean: we don't use the critical section.
00101     */
00102    m_bResumed = TRUE;
00103 }
00104 
00105 /**
00106  * set progress bar range; Note just store, OnTimer updates dialog.
00107  */
00108 void CProgressDlg::SetRange( int nLower, int nUpper )
00109 {
00110    /*
00111     * "produce":
00112     */
00113    m_criticalSection.Lock();
00114    m_nLowerPosition = nLower;
00115    m_nUpperPosition = nUpper;
00116    m_criticalSection.Unlock();
00117 }
00118 
00119 /**
00120  * set progress bar position; Note just store, OnTimer updates dialog.
00121  */
00122 void CProgressDlg::SetPos( int nPos )
00123 {
00124    /*
00125     * "produce":
00126     */
00127    m_criticalSection.Lock();
00128    m_nCurrentPosition = nPos;
00129    m_criticalSection.Unlock();
00130 }
00131 
00132 /**
00133  * set progress dialog message text; Note just store, OnTimer updates dialog.
00134  */
00135 void CProgressDlg::SetText( LPCTSTR lpcsText )
00136 {
00137    /*
00138     * "produce":
00139     */
00140    m_criticalSection.Lock();
00141    m_csMessage = lpcsText;
00142    m_criticalSection.Unlock();
00143 }
00144 
00145 /**
00146  * close the progress dialog window.
00147  */
00148 void CProgressDlg::Terminate()
00149 {
00150    /**
00151     * give dialog a chance to get initialized and show itself.
00152     *
00153     * this only affects computation threads that already have finished before
00154     * the dialog has been completely initialized.
00155     */
00156    while ( !m_bInitialized )
00157    {
00158       Sleep( 50 );
00159    }
00160 
00161    if ( !IsCanceling() )
00162    {
00163       ::PostMessage( m_hWnd, WM_CLOSE, 0, 0 );
00164    }
00165 }
00166 
00167 /**
00168  * show as modal dialog box, resume computation thread.
00169  */
00170 int CProgressDlg::DoModal( CWinThread *pThread )
00171 {
00172    /*
00173     * resume computation thread and show the modal dialog:
00174     */
00175    return ResumeComputationThread( pThread )
00176        && CDialog::DoModal();
00177 }
00178 
00179 /**
00180  * exchange dialog.
00181  */
00182 void CProgressDlg::DoDataExchange( CDataExchange* pDX )
00183 {
00184 //   Q_LOG( _T("CProgressDlg::DoDataExchange()") );
00185 
00186    CDialog::DoDataExchange(pDX);
00187 
00188    //{{AFX_DATA_MAP(CProgressDlg)
00189    //}}AFX_DATA_MAP
00190 }
00191 
00192 /**
00193  * the message map.
00194  */
00195 BEGIN_MESSAGE_MAP(CProgressDlg, CDialog)
00196    //{{AFX_MSG_MAP(CProgressDlg)
00197    ON_WM_TIMER()
00198    ON_WM_CLOSE()
00199    ON_BN_CLICKED( IDCANCEL, OnCancel )
00200    //}}AFX_MSG_MAP
00201 END_MESSAGE_MAP()
00202 
00203 /*
00204  * initialize the dialog.
00205  */
00206 BOOL CProgressDlg::OnInitDialog()
00207 {
00208    CDialog::OnInitDialog();
00209 
00210    /*
00211     * attach this dialog to the Objective Toolkit's advanced progress bar:
00212     */
00213    m_wndProgress.AttachProgress( IDC_PROGRESS, this );
00214 
00215    /*
00216     * attach this dialog to the Objective Toolkit's advanced progress bar:
00217     */
00218    (void) CWnd::SetTimer( c_nTimerIDEvent, 50 /* ms */, NULL );
00219 
00220    /*
00221     * indicate that dialog has been initialized, see also Terminate():
00222     */
00223    m_bInitialized = TRUE;
00224 
00225    return TRUE;
00226 }
00227 
00228 /**
00229  * handle cancel message;
00230  * OnCancel may be called as a result of pressing the Cancel button, of
00231  * pressing the Esc-key or as a result of sending WM_CLOSE to the dialog.
00232  */
00233 void CProgressDlg::OnCancel()
00234 {
00235 //  Q_LOG( "CProgressDlg::OnCancel()" );
00236 
00237    /*
00238     * signal computation thread to stop:
00239     */
00240    m_bCancel = TRUE;
00241 
00242    /*
00243     * wait for computation thread to finish, unless it was not (yet) resumed:
00244     */
00245    if ( IsResumed() )
00246    {
00247       (void) WaitForSingleObject( m_pThread->m_hThread, INFINITE );
00248    }
00249 
00250    /*
00251     * stop the timer:
00252     */
00253    (void) CWnd::KillTimer( c_nTimerIDEvent );
00254 
00255 //   Q_ASSERT( FALSE != KillTimer( c_nTimerIDEvent ) && "failed to kill progress dialog timer" );
00256 
00257    /*
00258     * the rest of the work:
00259     */
00260    CDialog::OnCancel();
00261 }
00262 
00263 /**
00264  * handle OnClose event.
00265  */
00266 void CProgressDlg::OnClose()
00267 {
00268    CDialog::OnCancel();
00269 }
00270 
00271 /**
00272  * handle timer event: update progress dialog.
00273  */
00274 void CProgressDlg::OnTimer( UINT nIDEvent )
00275 {
00276    if ( nIDEvent == c_nTimerIDEvent )
00277    {
00278       /*
00279        * "consume":
00280        */
00281       m_criticalSection.Lock();
00282 
00283       SetDlgItemText( IDC_PROGRESSTEXT, m_csMessage );
00284       m_wndProgress.SetRange( m_nLowerPosition, m_nUpperPosition );
00285       m_wndProgress.SetPos( m_nCurrentPosition );
00286 
00287       m_criticalSection.Unlock();
00288    }
00289 }
00290 
00291 /**
00292  * resume the given thread.
00293  */
00294 int CProgressDlg::ResumeComputationThread( CWinThread *pThread )
00295 {
00296    /*
00297     * save thread for later use in OnCancel():
00298     */
00299    m_pThread = pThread;
00300 
00301    /*
00302     * resume the computation thread:
00303     *
00304     * ResumeThread() returns the thread’s previous suspend count if successful:
00305     *  0: the current thread was not suspended
00306     *  1: the thread was suspended, but is now restarted
00307     * >1: the thread remains suspended.
00308     * 0xFFFFFFFF: error
00309     */
00310    if ( m_pThread->ResumeThread() != 1 )
00311    {
00312       LPVOID lpMsgBuf;
00313 
00314       ::FormatMessage(
00315          FORMAT_MESSAGE_ALLOCATE_BUFFER |
00316          FORMAT_MESSAGE_FROM_SYSTEM |
00317          FORMAT_MESSAGE_IGNORE_INSERTS, // source and processing options
00318          NULL,                          // pointer to  message source
00319          GetLastError(),                // requested message identifier
00320          MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), // default language
00321          (LPTSTR) &lpMsgBuf,            // pointer to message buffer
00322          0,                             // maximum size of message buffer
00323          NULL                           // pointer to array of message inserts
00324       );
00325 
00326       /*
00327        * log the error and free the buffer:
00328        */
00329       Q_LOG( (LPCTSTR) ( CString("ResumeThread: ") + (LPCTSTR) lpMsgBuf ) );
00330       LocalFree( lpMsgBuf );
00331 
00332       /*
00333        * inform user:
00334        */
00335       ::MessageBox(
00336          this->m_hWnd,
00337          _T( "Could not start the computation thread.\n\n"
00338              "Details have been written to the log file." ),
00339          _T( "Thread start failure" ),
00340          MB_ICONSTOP | MB_OK
00341       );
00342 
00343       /*
00344        * return error:
00345        */
00346       return FALSE;
00347    }
00348 
00349    /*
00350     * thread signals via SetResumed() that it has been resumed.
00351     */
00352    SetResumed();
00353 
00354    return TRUE;
00355 }
00356 
00357 /*
00358  * end of file
00359  */

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy