Make Modal Dialogs Behave Like Modeless Dialogs | CodeGuru

Make Modal Dialogs Behave Like Modeless Dialogs

Environment: Visual C++ 4.0 (and above) Description This template class simulates the behaviour of a modeless dialog while allowing some of the programmatic control of a modal dialog. When modal dialog are closed control is immediately returned to the caller of the DoModal member function: CMyDialog dlg; if( dlg.DoModal() ) { … } However, the […]

Written By
CodeGuru Staff
CodeGuru Staff
Jan 29, 2001
1 minute read
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Environment: Visual C++ 4.0 (and above)

Description

This template class simulates the behaviour of a modeless dialog while allowing some
of the programmatic control of a modal dialog. When modal dialog are closed control is
immediately returned to the caller of the DoModal member function:

CMyDialog dlg;
if( dlg.DoModal() ) { ... }

However, the same can not be said of modal dialogs where the Create/ShowWindow member
function pair need to be used in order to display the dialog.

CMyDialog dlg;
dlg.Create( IDD_MY_DIALOG );
dlg.ShowWindow();

...

if( you receive some message that the non-modal has closed )
{
...
}

The above code segment creates and activates a non-modal dialog. How and when you get
control back generally involves some rather tricky programming – in other words, it’s not
nearly as straight-forward as using a modal dialog.

Usage

NonModalDialog<MyDlg>myDlg( AfxGetMainWnd() );
myDlg.DoModal();
...
class CWnd;
template <class ModalDialog>class NonModalDialog
: public ModalDialog
{
public :
 NonModalDialog( CWnd *pParent )
 : ModalDialog( pParent ) { }
 virtual int DoModal();
 virtual void EndModalLoop( int );
protected:
 int m_nStillActive;
};
template <class ModalDialog>
inline int NonModalDialog<ModalDialog>::DoModal()
{
 MSG			l_objMessage;
 CWinThread*	l_pThread = AfxGetThread();
 ASSERT_VALID( l_pThread );
 Create( ModalDialog::IDD );
 ShowWindow( SW_SHOW );
 m_nStillActive = 1;
 //--------- Thanks to Microsoft. This block 
 //--------- is from CWinThread::Run
 // from Thrdcore.cpp, with appropriate changes.
 ASSERT_VALID(this);
 // for tracking the idle time state
 BOOL l_nIdle = TRUE;
 LONG l_nIdleCount = 0;
 // acquire and dispatch messages until 
 // a WM_QUIT message is received,
 // or the dialog box is closed.
 for (;;)
 {
  // phase1: check to see if we can do idle work
  while( l_nIdle && !::PeekMessage( &l_objMessage,
                                    NULL,
                                    NULL,
                                    NULL,
                                    PM_NOREMOVE ) )
  {
   // call OnIdle while in bIdle state
   if( !l_pThread->OnIdle( l_nIdleCount++ ) )
    l_nIdle = FALSE; // assume "no idle" state
  }
  // phase2: pump messages while available
  do
  {
   // Relent control back to Windows if the dialog 
   // box has closed.
   if( !m_nStillActive )
    return m_nModalResult;
   if( l_objMessage.message == WM_SYSCOMMAND
   && l_objMessage.wParam == SC_CLOSE )
    OnCancel();	// Close the dialog box first.
   // pump message, but quit on WM_QUIT
   if( !l_pThread->PumpMessage() )
    return l_pThread->ExitInstance();
   // reset "no idle" state after pumping 
   // "normal" message
   if( l_pThread->IsIdleMessage( &l_objMessage ) )
    l_nIdle = TRUE, l_nIdleCount = 0;
  } while( ::PeekMessage( &l_objMessage,
                          NULL,
                          NULL,
                          NULL,
                          PM_NOREMOVE ) );
 }
 ASSERT(FALSE);  // not reachable
 //---------------------
}
template <class ModalDialog>inline void
NonModalDialog<ModalDialog>::EndModalLoop(int p_nResult)
{
 m_nStillActive = 0;
 ModalDialog::EndModalLoop( p_nResult );
}
Advertisement

Limitations

  1. Applies only to MFC versions that properly support OCX containment. ( v4.0 and later )
  2. From inside the dialog, you close it using EndDialog( ... ) only.
  3. You MUST take only two parameters, one is the IDD of your dialog, and the next is CWnd*, in your dialog's constructor.
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2026 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.