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
| Вернуться в корень Архива |