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

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


AfxMessageBox() in Dialog Based Application

Hans Wedemeyer -- hansw@sprintmail.com
Friday, January 17, 1997

Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)

Why does AfxMessageBox() instantly return IDOK when used in a dialog
based application,and NOT display the message.

Code sample taken from standard VC++ generated dialog based aplication
skeleton code in the InitInstance()


	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
	  int n=0;	
	  AfxMessageBox("Test Message!",MB_OK);// does not display
          TRACE("AfxMess Returned %d\n",n);	
        }
	else if (nResponse ........

I thought this was a global function that could work in difficult
situations, even before a window is created.. Where as MessageBox()
requires a valid CWnd pointer.   
Any help is appreciated
Hans Wedemeyer
hansw@sprintmail.com



Mike Blaszczak -- mikeblas@nwlink.com
Sunday, January 19, 1997

[Mini-digest: 5 responses]

At 11:45 1/17/97 -0600, Hans Wedemeyer wrote:
>Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)

>Why does AfxMessageBox() instantly return IDOK when used in a dialog
>based application,and NOT display the message.

This sentence doesn't completely explain the problem you're having.
The application is not displaying the message because you've already
told it to shut down.

>Code sample taken from standard VC++ generated dialog based aplication
>skeleton code in the InitInstance()
>
>	m_pMainWnd = &dlg;
>	int nResponse = dlg.DoModal();
>	if (nResponse == IDOK)
>	{
>	  int n=0;	
>	  AfxMessageBox("Test Message!",MB_OK);// does not display
>          TRACE("AfxMess Returned %d\n",n);	
>        }
>	else if (nResponse ........

That's not correct: AppWizard didn't generate any of
the "AfxMessageBox()" code.  It's impossible to have AppWizard
generate this code.  Obviously, it's something you've coded yourself,
and as such, it's inappropriate for you to claim that this is
part of the "VC++ generated dialog based application skeleton code".

Your code is broken for two reasons.  Let's take the minor problem first:

First, you set n=0 in the initializer and then use it in a TRACE
message, but you've never assigned it to anything. Your trace message
will _always_ say that "AfxMess" returned zero.

Second, your application is over. You've said that m_pMainWnd is
your dialog box, and that means you're telling MFC that the main
window of your application is that dialog box. One of the semantic
meanings of "main window" is that it's the window that runs the
application--if the window closes the application is on its way down.

Since you've returned from DoModal(), the main window is destroyed and
MFC has processed a WM_QUIT message.  MFC is no longer pumping messages
for the application, since the application is over.  Though you've told
MFC the application is over, you're trying to pop up a dialog box.
Since MFC is already done processing messages, it doesn't ever display
the box (because displaying the box would require MFC to process more
messages, but it can't, since you've already given it a WM_QUIT message
to process).

You can fix this problem by overriding PostNcDestroy() so that it
doesn't post a WM_QUIT message, or by not setting your m_pMainWnd
to your dialog.

>I thought this was a global function that could work in difficult
>situations,

No, it isn't. If you code sloppily with _any_ function, you'll get
into trouble. If you pop up a message box in response to WM_GETFOCUS,
for example, you'll probably end up crashing, since the message box
will, itself, kill focus from the window, and then ...

> Where as MessageBox() requires a valid CWnd pointer.   

The ::MessageBox() API can be called passing NULL for its
parent window parameter.  The CWnd::MessageBox() function doesn't
take a CWnd* parameter (then again, neither does the ::MessageBox()
API).


.B ekiM
http://www.nwlink.com/~mikeblas/      <-- trip report central!
95 Honda VFR-750F / 88 Yamaha FZ-700 (damaged) / 94 Mazda RX-7
Serial #00050!    /      AMA - HRC - VFROC     / Wang Dang Wankel
         I am bored of this talk. It is time now for the dancing!
These words are my own - I do not speak on behalf of Microsoft.


-----From: Hugues MEUNIER 



----------
De : 	Hans Wedemeyer[SMTP:hansw@sprintmail.com]
Date d'envoi :	vendredi 17 janvier 1997 18:45
A :	mfc-l@netcom.com
Objet :	AfxMessageBox() in Dialog Based Application

Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)

Why does AfxMessageBox() instantly return IDOK when used in a dialog
based application,and NOT display the message.

Code sample taken from standard VC++ generated dialog based aplication
skeleton code in the InitInstance()


try 
	m_pMainWnd = &dlg;
	if (dlg.DoModal() == IDOK)
	{
	  int n=0;	
	  AfxMessageBox("Test Message!",MB_OK);// does not display
          TRACE("AfxMess Returned %d\n",n);	
        }
	else if (nResponse ........

-----From: David Little 

	m_pMainWnd = &dlg;
	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
	  int n=0;	
	  AfxMessageBox("Test Message!",MB_OK);// does not display
          TRACE("AfxMess Returned %d\n",n);	
        }
	else if (nResponse ........

>> Your trace statement will always return a 0.  Put a breakpoint on the box and step into it....It could be returning an error.

I thought this was a global function that could work in difficult
situations, even before a window is created.. Where as MessageBox()
requires a valid CWnd pointer.   
>> You can use a NULL as the HWND parameter and it will work.


-----From: "Dean Wiles" 

I'm guessing here, but after your call to dlg.DoModal() the dlg's m_hWnd is
destroyed and hence the contents of m_pMainWnd is not a valid handle which
I think is what AfxMessageBox uses.  Look at the source code for
AfxMessageBox or use ::MessageBox(::GetFocus(), ...).

Hope this is  helpful.

--------------------------------------------------------------------------
Dean Wiles (deanw@mail.isc-br.com)          Olivetti North America
Phone:  (509)927-7037                       22425 East Appleway Ave
Fax:    (509)927-2499                       Liberty Lake, WA 99019-9534
If the Son sets you free, you will be free indeed.  (John 8:36)

----------
> From: Hans Wedemeyer 
> To: mfc-l@netcom.com
> Subject: AfxMessageBox() in Dialog Based Application
> Date: Friday, January 17, 1997 9:45 AM
> 
> Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)
> 
> Why does AfxMessageBox() instantly return IDOK when used in a dialog
> based application,and NOT display the message.
> 
> Code sample taken from standard VC++ generated dialog based aplication
> skeleton code in the InitInstance()
> 
> 
> 	m_pMainWnd = &dlg;
> 	int nResponse = dlg.DoModal();
> 	if (nResponse == IDOK)
> 	{
> 	  int n=0;	
> 	  AfxMessageBox("Test Message!",MB_OK);// does not display
>           TRACE("AfxMess Returned %d\n",n);	
>         }
> 	else if (nResponse ........
> 
> I thought this was a global function that could work in difficult
> situations, even before a window is created.. Where as MessageBox()
> requires a valid CWnd pointer.   
> Any help is appreciated
> Hans Wedemeyer
> hansw@sprintmail.com
-----From: Joao Marcos Melo Mendes 

Hello, :)

On Fri, 17 Jan 1997, Hans Wedemeyer wrote:

> 	m_pMainWnd = &dlg;
> 	int nResponse = dlg.DoModal();
> 	if (nResponse == IDOK)
> 	{
> 	  int n=0;	
> 	  AfxMessageBox("Test Message!",MB_OK);// does not display
>           TRACE("AfxMess Returned %d\n",n);	
>         }
> 	else if (nResponse ........

If this really is your code, I would note that you do not assign anything 
to n, so that your trace would always read 0.
If, however, this was a transcription error, and you do indeed assign the 
return value of AfxMessageBox, I would point out that a return value of 0 
indicates that the machine does not have enough memory to display the 
message box, and that IDOK is defined as 1, not 0.

Then again, you may already know all of this, in which case I cannot be 
of much help. I can only offer one suggestion: MFCs often act up when 
used as statically linked libraries instead of DLLs, or when the linking 
mode changes throughout the development of the project. Perhaps you might 
try relinking your project with the MFC as a DLL.
This is something that has worked for me on occasions too numerous to 
mention, the last one having been this very morning.

I hope all of this has been of some help...

                                        Joao Mendes
                                        MegaMedia, S.A.

"We're fools to make war on our brothers in arms." - Mark Knopfler

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: 2.6.2

mQBNAzKu3TgAAAECAL8+YSEFZ0XrlBMu9t2xDq3rhpWZoscP83VrX5MevAm3UOd6
fOtDKsJxsWugnVMexo50NfBjeWOHz5nA1b9hYx0ABRG0H0pvYW8gTWVuZGVzIDxq
bW1tQG1lZ2FtZWRpYS5wdD4=
=sspP
-----END PGP PUBLIC KEY BLOCK-----




Eric Kenslow -- EricK@MetaInfo.com
Monday, January 20, 1997

[Mini-digest: 4 responses]

Try explicitly setting your m_pMainWnd member to 0 before the call to
AfxMessageBox().

>----------
>From: 	Hans Wedemeyer[SMTP:hansw@sprintmail.com]
>Sent: 	Friday, January 17, 1997 9:45 AM
>To: 	mfc-l@netcom.com
>Subject: 	AfxMessageBox() in Dialog Based Application
>
>Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)
>
>Why does AfxMessageBox() instantly return IDOK when used in a dialog
>based application,and NOT display the message.
>
>Code sample taken from standard VC++ generated dialog based aplication
>skeleton code in the InitInstance()
>
>
>	m_pMainWnd = &dlg;
>	int nResponse = dlg.DoModal();
>	if (nResponse == IDOK)
>	{
>	  int n=0;	
>	  AfxMessageBox("Test Message!",MB_OK);// does not display
>          TRACE("AfxMess Returned %d\n",n);	
>        }
>	else if (nResponse ........
>
>I thought this was a global function that could work in difficult
>situations, even before a window is created.. Where as MessageBox()
>requires a valid CWnd pointer.   
>Any help is appreciated
>Hans Wedemeyer
>hansw@sprintmail.com
>
-----From: Mike Blaszczak 

>-----From: "Dean Wiles" 

>I'm guessing here, but after your call to dlg.DoModal() the dlg's m_hWnd is
>destroyed and hence the contents of m_pMainWnd is not a valid handle which
>I think is what AfxMessageBox uses. Look at the source code for
>AfxMessageBox or use ::MessageBox(::GetFocus(), ...).

m_pMainWnd is set to NULL, which is actually quite valid for the parent
parameter to the eventual ::MessageBox() API call.

>-----From: Joao Marcos Melo Mendes 

>I can only offer one suggestion: MFCs often act up when 
>used as statically linked libraries instead of DLLs, or when the linking 
>mode changes throughout the development of the project.

Do you have any evidence to support this assertion?  If you have some
reproducable case where code for an application breaks in a static library,
please let me know and I'll get it fixed.  If you _can't_ offer real
evidence that shows problems exist with switching MFC linking models,
I'd really, really appreciate it if you'd please refrain from casting
such unfounded aspersions.

>Perhaps you might try relinking your project with the MFC as a DLL.

Please, please try to stick to offering real advice. This suggestion is
just snake oil--this problem has absolutely nothing to do with the linking
model, and can be solidly explained by a _real_ diagnosis.  The problem
involves only a few extra lines of code above what AppWizard produces, and
you can trivially verifiy for yourself that the behaviour the original
poster noted can be replicated whether you statically link or not.


.B ekiM
http://www.nwlink.com/~mikeblas/
Why does the "new" Corvette look like a 1993 RX-7?
These words are my own. I do not speak on behalf of Microsoft.

-----From: Christophe Nasarre  

>Christophe Nasarre wrote:
>>Stop !
>>Have you tried calling AfxMessageBox BEFORE your main dialog DoModal()?
>> No ?... It works...
>> ....
>> Sure a good MFC bug...
>>

Well... My mail was a little bit longer.

>-------------------------------------------------------------------
Hans wrote:

> Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)
> 
> Why does AfxMessageBox() instantly return IDOK when used in a dialog
> based application,and NOT display the message.
> 
> Code sample taken from standard VC++ generated dialog based aplication
> skeleton code in the InitInstance()
> 
> m_pMainWnd = &dlg;
> int nResponse = dlg.DoModal();
> if (nResponse == IDOK)
> {
>    int n=0;
>    AfxMessageBox("Test Message!",MB_OK);// does not display
>    TRACE("AfxMess Returned %d\n",n);
> }
> else if (nResponse ........
> 
> I thought this was a global function that could work in difficult
> situations, even before a window is created.. Where as MessageBox()
> requires a valid CWnd pointer.
> Any help is appreciated

You should take a look at the implementation of AfxMessageBox() in APPUI.CPP.
It calls CWinApp::DoMessageBox() in the same CPP file and if the main
window (m_pMainWnd) is not a valid window (and this is the case after
DoModal()), the Win32 API ::MessageBox(NULL, ...) is called. And, I was
surprised but ::MessageBox(NULL, is not understood as a message box with the
desktop as parent... No message is displayed but 1 is returned...

That was not my last surprise : ::MessageBox(::GetDesktopWindow(),
does not work. And ::MessageBox(::GetActiveWindow() neither since
::GetActiveWindow() returns NULL (no more active window in the thread)

Well... I remembered that activation and focus is stored on a per thread
basis in Win32 so I have tried ::GetForeGroundWindow() but if you
call ::MessageBox on it, you just freeze it without displaying any
message box !

To sum up, I'm not able to give you a simple solution using MessageBox
But why don't you create another simple dialog to display your message
and call it using DoModal ;-)

Stop !
Have you tried calling AfxMessageBox BEFORE your main dialog DoModal() ?
No ?... It works... (and ::MessageBox(NULL,...) too)

I have debugged through the hooks installed by MFC (but never uninstalled
if your code is not in a DLL) to follow the call of ::MessageBox inside 
AfxMessageBox() and everything works great (created, centered, moved) but 
it is destroyed just after having moved. Don't ask me why !:-)

Sure a good MFC bug...
>-------------------------------------------------------------------

Good luck

   Christophe -- a poor lonely frenchie --

-----From: Steve Dunn 

Environment: MSVC 4.2b Windows NT 4.0

I have a dialog base application that spawns off up to 5 modeless dialog =
boxes.  I want for whatever window (the main modal dialog, or the =
modeless dialogs) to become the foremost window when they receive the =
focus.
When I create the modeless dialogs and set the parent to the main =
application window, the Z order is created in the order the modeless =
dialogs are created.  The problem with this is that I cannot bring =
whatever window gets the focus to the front of the z order.  I've =
overridden OnGetFocus, OnActivate etc. with no luck.

I've now set the parent of the modeless dialogs to the desktop window =
with GetDesktopWindow().  The z-order now looks after itself, with the =
only problem, and my main question being, that I cannot intercept =
WM_CLOSE, WM_DESTROY even though I can see the messages being received =
by the window using spy-xx.

Steve Dunn




Eric Kenslow -- EricK@MetaInfo.com
Monday, January 20, 1997

[Mini-digest: 4 responses]

Try explicitly setting your m_pMainWnd member to 0 before the call to
AfxMessageBox().

>----------
>From: 	Hans Wedemeyer[SMTP:hansw@sprintmail.com]
>Sent: 	Friday, January 17, 1997 9:45 AM
>To: 	mfc-l@netcom.com
>Subject: 	AfxMessageBox() in Dialog Based Application
>
>Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)
>
>Why does AfxMessageBox() instantly return IDOK when used in a dialog
>based application,and NOT display the message.
>
>Code sample taken from standard VC++ generated dialog based aplication
>skeleton code in the InitInstance()
>
>
>	m_pMainWnd = &dlg;
>	int nResponse = dlg.DoModal();
>	if (nResponse == IDOK)
>	{
>	  int n=0;	
>	  AfxMessageBox("Test Message!",MB_OK);// does not display
>          TRACE("AfxMess Returned %d\n",n);	
>        }
>	else if (nResponse ........
>
>I thought this was a global function that could work in difficult
>situations, even before a window is created.. Where as MessageBox()
>requires a valid CWnd pointer.   
>Any help is appreciated
>Hans Wedemeyer
>hansw@sprintmail.com
>
-----From: Mike Blaszczak 

>-----From: "Dean Wiles" 

>I'm guessing here, but after your call to dlg.DoModal() the dlg's m_hWnd is
>destroyed and hence the contents of m_pMainWnd is not a valid handle which
>I think is what AfxMessageBox uses. Look at the source code for
>AfxMessageBox or use ::MessageBox(::GetFocus(), ...).

m_pMainWnd is set to NULL, which is actually quite valid for the parent
parameter to the eventual ::MessageBox() API call.

>-----From: Joao Marcos Melo Mendes 

>I can only offer one suggestion: MFCs often act up when 
>used as statically linked libraries instead of DLLs, or when the linking 
>mode changes throughout the development of the project.

Do you have any evidence to support this assertion?  If you have some
reproducable case where code for an application breaks in a static library,
please let me know and I'll get it fixed.  If you _can't_ offer real
evidence that shows problems exist with switching MFC linking models,
I'd really, really appreciate it if you'd please refrain from casting
such unfounded aspersions.

>Perhaps you might try relinking your project with the MFC as a DLL.

Please, please try to stick to offering real advice. This suggestion is
just snake oil--this problem has absolutely nothing to do with the linking
model, and can be solidly explained by a _real_ diagnosis.  The problem
involves only a few extra lines of code above what AppWizard produces, and
you can trivially verifiy for yourself that the behaviour the original
poster noted can be replicated whether you statically link or not.


.B ekiM
http://www.nwlink.com/~mikeblas/
Why does the "new" Corvette look like a 1993 RX-7?
These words are my own. I do not speak on behalf of Microsoft.

-----From: Christophe Nasarre  

>Christophe Nasarre wrote:
>>Stop !
>>Have you tried calling AfxMessageBox BEFORE your main dialog DoModal()?
>> No ?... It works...
>> ....
>> Sure a good MFC bug...
>>

Well... My mail was a little bit longer.

>-------------------------------------------------------------------
Hans wrote:

> Environment: MSVC 4.2b Windows NT 4.0 (SP2 + hotfix)
> 
> Why does AfxMessageBox() instantly return IDOK when used in a dialog
> based application,and NOT display the message.
> 
> Code sample taken from standard VC++ generated dialog based aplication
> skeleton code in the InitInstance()
> 
> m_pMainWnd = &dlg;
> int nResponse = dlg.DoModal();
> if (nResponse == IDOK)
> {
>    int n=0;
>    AfxMessageBox("Test Message!",MB_OK);// does not display
>    TRACE("AfxMess Returned %d\n",n);
> }
> else if (nResponse ........
> 
> I thought this was a global function that could work in difficult
> situations, even before a window is created.. Where as MessageBox()
> requires a valid CWnd pointer.
> Any help is appreciated

You should take a look at the implementation of AfxMessageBox() in APPUI.CPP.
It calls CWinApp::DoMessageBox() in the same CPP file and if the main
window (m_pMainWnd) is not a valid window (and this is the case after
DoModal()), the Win32 API ::MessageBox(NULL, ...) is called. And, I was
surprised but ::MessageBox(NULL, is not understood as a message box with the
desktop as parent... No message is displayed but 1 is returned...

That was not my last surprise : ::MessageBox(::GetDesktopWindow(),
does not work. And ::MessageBox(::GetActiveWindow() neither since
::GetActiveWindow() returns NULL (no more active window in the thread)

Well... I remembered that activation and focus is stored on a per thread
basis in Win32 so I have tried ::GetForeGroundWindow() but if you
call ::MessageBox on it, you just freeze it without displaying any
message box !

To sum up, I'm not able to give you a simple solution using MessageBox
But why don't you create another simple dialog to display your message
and call it using DoModal ;-)

Stop !
Have you tried calling AfxMessageBox BEFORE your main dialog DoModal() ?
No ?... It works... (and ::MessageBox(NULL,...) too)

I have debugged through the hooks installed by MFC (but never uninstalled
if your code is not in a DLL) to follow the call of ::MessageBox inside 
AfxMessageBox() and everything works great (created, centered, moved) but 
it is destroyed just after having moved. Don't ask me why !:-)

Sure a good MFC bug...
>-------------------------------------------------------------------

Good luck

   Christophe -- a poor lonely frenchie --

-----From: Steve Dunn 

Environment: MSVC 4.2b Windows NT 4.0

I have a dialog base application that spawns off up to 5 modeless dialog =
boxes.  I want for whatever window (the main modal dialog, or the =
modeless dialogs) to become the foremost window when they receive the =
focus.
When I create the modeless dialogs and set the parent to the main =
application window, the Z order is created in the order the modeless =
dialogs are created.  The problem with this is that I cannot bring =
whatever window gets the focus to the front of the z order.  I've =
overridden OnGetFocus, OnActivate etc. with no luck.

I've now set the parent of the modeless dialogs to the desktop window =
with GetDesktopWindow().  The z-order now looks after itself, with the =
only problem, and my main question being, that I cannot intercept =
WM_CLOSE, WM_DESTROY even though I can see the messages being received =
by the window using spy-xx.

Steve Dunn





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