15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Using throw() during DoModal() calls

Carl Downs -- cdowns@dev.tivoli.com
Friday, November 22, 1996

Environment: VC++ 4.0, NT 3.51

I'm trying to execute a throw from within a modal dialog box.  

I call DoModal() as usual.  The OnHelp() event method
throws, and control returns (from DoModal) to the
catch (CString msg).

Everything works as expected, except that once the catch
completes executing, the main program cannot receive
focus!  It must be killed from the system's task list.

This code snippet exhibits the problem:

/////////////////////////////////////////////////////////////////////////////
// App command to run the dialog
void CDriverApp::OnAppAbout()
{
	CAboutDlg *aboutDlg = new CAboutDlg;
	try 
	{
		aboutDlg->DoModal();
	}
	catch (CString msg)
	{
                AfxMessageBox (msg);
	}
	catch (...)
	{
                AfxMessageBox ("Unknown Exception caught...");
	}

 	delete aboutDlg;
}

/////////////////////////////////////////////////////////////////////////////
class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	afx_msg void OnHelp();
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////
// CDriverApp commands

void CAboutDlg::OnHelp() 
{
	throw CString ("Help not available.");
}

/////////////////////////////////////////////////////////////////////////////


This problem occurs regardless of whether I place the CAboutDlg instance
on the stack or heap.

VC displays this warning as the delete method is called on 
the dialog box object:

Warning: calling DestroyWindow in CDialog::~CDialog --
	OnDestroy or PostNcDestroy in derived class will not be called.

If no exception is thrown, the delete method call works.

Anyone know how I can make CDialog derived class methods throwable?

Thanks
Carl




Rick Rankin -- RickR@fscrater.com
Monday, November 25, 1996

[Mini-digest: 3 responses]

There is a good article in MSJ that should answer your questions. The
bottom line is that you can't throw exceptions across callback
boundaries. MSJ November 1996 starting on page 104.

>----------
>From: 	cdowns@dev.tivoli.com[SMTP:cdowns@dev.tivoli.com]
>Sent: 	Friday, November 22, 1996 7:30 AM
>To: 	mfc-l@netcom.com
>Subject: 	Using throw() during DoModal() calls
>
>Environment: VC++ 4.0, NT 3.51
>
>I'm trying to execute a throw from within a modal dialog box.  
>
>I call DoModal() as usual.  The OnHelp() event method
>throws, and control returns (from DoModal) to the
>catch (CString msg).
>
>Everything works as expected, except that once the catch
>completes executing, the main program cannot receive
>focus!  It must be killed from the system's task list.
>
>This code snippet exhibits the problem:
>
>/////////////////////////////////////////////////////////////////////////////
>// App command to run the dialog
>void CDriverApp::OnAppAbout()
>{
>	CAboutDlg *aboutDlg = new CAboutDlg;
>	try 
>	{
>		aboutDlg->DoModal();
>	}
>	catch (CString msg)
>	{
>                AfxMessageBox (msg);
>	}
>	catch (...)
>	{
>                AfxMessageBox ("Unknown Exception caught...");
>	}
>
> 	delete aboutDlg;
>}
>
>/////////////////////////////////////////////////////////////////////////////
>class CAboutDlg : public CDialog
>{
>public:
>	CAboutDlg();
>
>// Dialog Data
>	//{{AFX_DATA(CAboutDlg)
>	enum { IDD = IDD_ABOUTBOX };
>	//}}AFX_DATA
>
>	// ClassWizard generated virtual function overrides
>	//{{AFX_VIRTUAL(CAboutDlg)
>	protected:
>	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
>	//}}AFX_VIRTUAL
>
>// Implementation
>protected:
>	//{{AFX_MSG(CAboutDlg)
>	afx_msg void OnHelp();
>	//}}AFX_MSG
>	DECLARE_MESSAGE_MAP()
>};
>
>/////////////////////////////////////////////////////////////////////////////
>// CDriverApp commands
>
>void CAboutDlg::OnHelp() 
>{
>	throw CString ("Help not available.");
>}
>
>/////////////////////////////////////////////////////////////////////////////
>
>
>This problem occurs regardless of whether I place the CAboutDlg instance
>on the stack or heap.
>
>VC displays this warning as the delete method is called on 
>the dialog box object:
>
>Warning: calling DestroyWindow in CDialog::~CDialog --
>	OnDestroy or PostNcDestroy in derived class will not be called.
>
>If no exception is thrown, the delete method call works.
>
>Anyone know how I can make CDialog derived class methods throwable?
>
>Thanks
>Carl
>
>
-----From: "Eric Kenslow" 

Your problem is that MFC is explicitly disabling your app's main window.
You need to re-enable it in your catch clauses.

If you check the MFC source for DoModal(), you'll see what I mean. I'd
provide some code, but it's pretty late and I've been coding for 10 hours
already :)...

/* Eric Kenslow - Developer, MetaInfo Inc.
 * EricK@metainfo.com
 */

-----From: zhangdh.bbs@bbs.net.tsinghua.edu.cn

>I call DoModal() as usual.  The OnHelp() event method
>throws, and control returns (from DoModal) to the
>catch (CString msg).
>
>
>/////////////////////////////////////////////////////////////////////////////
 // App command to run the dialog
>void CDriverApp::OnAppAbout()
>{
>       CAboutDlg *aboutDlg = new CAboutDlg;
>       try 
>       {
>               aboutDlg->DoModal();
>       }
>       catch (CString msg)
>       {
>                 AfxMessageBox (msg);
        //ADD here
                AfxMessageBox (msg);
                  aboutDlg->DestroyWindow();
                  delete aboutDlg;
                  (GetMainWnd())->EnableWindow();
                  return;
        
>       }
>       catch (...)
>       {
>                 AfxMessageBox ("Unknown Exception caught...");
        //ADD here         
                        aboutDlg->DestroyWindow();
                        delete aboutDlg;
                        return;

>       }
>
>       delete aboutDlg;
>}
>
>
>This problem occurs regardless of whether I place the CAboutDlg instance
>on the stack or heap.
>
> VC displays this warning as the delete method is called on 
>the dialog box object:
>
>Warning: calling DestroyWindow in CDialog::~CDialog --
>       OnDestroy or PostNcDestroy in derived class will not be called.
>
>If no exception is thrown, the delete method call works.
>
>Anyone know how I can make CDialog derived class methods throwable?
 BackGround:
MFC is sending a WM_DISABLEMODAL to all of the frame's descendant windows
when a modal dialog box pops up. But the exception cause the frame 
don't know that the dialog have over!





| Вернуться в корень Архива |