We help IT Professionals succeed at work.

Check out our new AWS podcast with Certified Expert, Phil Phillips! Listen to "How to Execute a Seamless AWS Migration" on EE or on your favorite podcast platform. Listen Now


CDialog::DoModal doesn't show the window

PC-Alex asked
Medium Priority
Last Modified: 2008-02-01
When calling DoModal of a CDialog derived object (an error message dialog),
it is not shown on the screen; the event OnShowWindow (WM_SHOWWINDOW) is not even reached.

The parent window is a CFrameWnd derived class having the attribute "DS_SYSMODAL",
and having one child window displayed.

When this child window is not yet created, the error message dialog is displayed;
but after creation of the child the error box isn't shown any more.

Even when the child window is parent of the error dialog, the error is invisible.

The error message comes out of a worker thread.
Watch Question

can you post some relevant code?

Do you have any incorrectly or unregistered ActiveX controls embedded on this dialog?  These errors will usually fail silently.

I agree with rayb.  

If you don't have your ActiveX control registered or you are missing a DLL that your ActiveX relies on, everything will start to initialize until the DoModal executes.  It will just return silently in the OnInitDialog.  If your dialog executes OnInitDialog but nothing else, look for it!



rayb and psdavis,
I don't use any ActiveX in my program at all, absolutely sure.
The error dialog contains one BMP and one static control.

you want to see code ? OK, the CMainFrame is made like this:
CMainFrame * pMainFrame = new CMainFrame;

. and the error dialog is just created in the resource editor, ClassWizard made a class of it and that was it. Do you want the code of the .rc file ?

How about the code that creates and shows the dialog?  or the code that creates the child window.

I don't use MFC, but the documentation I can find for LoadFrame() says that the styles are passed as the second parameter, but you are passing them as the first.  Is that a mistake or is this a different LoadFrame()?

Post the full CDialog class source code.  Also post the CMainFrame function that creates the dialog (look for DoModal).

It will be something like

CMyDialog pMyDialog;
pMyDialog.DoModal( );

I only do MFC.  You'll get both points of view!


How about...

DS_SYSMODAL on a CMainFrame?

 Creates a system-modal dialog box. This style causes the dialog box to have the WS_EX_TOPMOST style, but otherwise has no effect on the dialog box or the behavior of other windows in the system when the dialog box is displayed.
See if you can take the DS_SYSMODAL off of the CMainFrame and only put it on the dialog!  


Actually, the DS_SYSMODAL doesn't even do anything anymore.  That was Win3.1

I say, remove it for now and see if everything else works as normal.  You can always use a SetWindowPos to set the topmost style instead.



Removing DS_SYSMODAL has a pretty feasable effect; you can now fetch windows from the background above the FrameWnd (like a notepad, explorer etc).

When using DS_SYSMODAL, this is impossible, at least in a RELEASE Build (I wonder why in DEBUG mode this doesn't hold true, ... but that's not the problem).

nietod, my documentation about CFrameWnd::LoadFrame says:
virtual BOOL LoadFrame( UINT nIDResource, DWORD dwDefaultStyle = WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, CWnd* pParentWnd = NULL, CCreateContext* pContext = NULL );

One interesting point is that CriticalErrorDialog's hWnd is NULL between the constructor and the call to DoModal(). Is this alright ?

psdavis, removing DS_SYSMODAL out of the FrameWnd didn't change anything. Patching it into the RC file to the attributes of the IDD_DIALOG_CRITERROR also didn't change anything.
Finally some further code for those who asked:

// ErrorHandler.cpp:
void CErrorHandler::DisplayCriticalError(CString ErrorMessage)
  // here is the called CDialog that is not shown
  CErrorCritical CriticalErrorDialog(m_pParentWnd, ErrorMessage);

CErrorCritical::CErrorCritical(CWnd* pParent, CString strMessage)
      : CDialog(CErrorCritical::IDD, pParent)
  m_strMessage = strMessage;

void CErrorCritical::DoDataExchange(CDataExchange* pDX)
      DDX_Text(pDX, IDC_STATIC_MESSAGSE, m_strMessage);

BEGIN_MESSAGE_MAP(CErrorCritical, CDialog)

void CErrorCritical::OnShowWindow(BOOL bShow, UINT nStatus)
  CDialog::OnShowWindow(bShow, nStatus);  // is never reached !!

// ErrorHandler.h:
class CErrorCritical : public CDialog
// Construction
      CErrorCritical(CWnd* pParent = NULL, CString strMessage = "");   // standard constructor

// Dialog Data
      enum { IDD = IDD_DIALOG_CRITERROR };
      CString      m_strMessage;

// Overrides
      // ClassWizard generated virtual function overrides
      virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation

      // Generated message map functions
      afx_msg void OnShowWindow(BOOL bShow, UINT nStatus);
// resource file:
CAPTION "Fehlerüberwachung"
FONT 8, "MS Sans Serif"
    DEFPUSHBUTTON   "OK",IDOK,229,317,50,14
    CONTROL         141,IDC_STATIC,"Static",SS_BITMAP,7,7,271,273
    LTEXT           "Static",IDC_STATIC_MESSAGSE,7,286,214,45


Two points:

1.  One thing you said in your original message looks quite interesting.  You mention that the dialog box is created in a worker thread.  You also mention that the frame window is the parent.  Question?  How are you passing the pFrameWnd to the worker thread.  If you are accessing the pointer from the CWinApp then you have a problem.  You cannot access that pointer from a worker thread.  What you have to do is store the hwnd of the pFrameWnd someplace and then, in your worker thread, reinstantiate your frame window around it using FromHandle(HWND).  Like this:

In your main application thread:

CMyApp *pApp = (CMyApp *)AfxGetApp();
pApp->m_hFrame = pApp->m_pMainFrame->GetSafeHwnd();

Then, in your worker thread:

CMyFrame *pFrame = CMyFrame::FromHandle(((CMyApp *)AfxGetApp())->m_hFrame);
CErrorCritical dlg(ID, pFrame);

I didn't compile that code so you may have to futz with it a bit.  

2.  Make CERTAIN that your worker threads are created through CWinThread.  If they are not you will not be able to access ANY MFC object.  Look at "Multithreading:  Programming tips" for more on that.

Hope it helps.


the worker thread indeed is CWinThread derived. I tried your code, but that didn't change the behaviour of the program.
When I compare the parent window before and after this change, the m_hWnd is exactly the same.#
As I was told, worker threads don't have local CHandleMaps, only "real" UI-Threads do.

But nevertheless, the idea was good and I think I'm on the right track. Because I found out something that made me think:
I examined the state of the WinApp thread while the worker thread waits for a "OK" click in a window I don't see.
The WinApp thread is positioned at a "WaitForSingleObject(.., INFINITE)" command, waiting for the worker thread to set his "I'm finished!" event.

Could it be that the WinApp is deadlocked in that moment, not processing a WM_PAINT that must be executed in order to display the ErrorDialog ?
(I checked that by changing the "WaitForSingleObject(.., INFINITE)" into "while (WaitForSingleObject(.., 0) != WAIT_OBJECT_0) Sleep(0);", but that didn't change anything)

Is there a possibility to call something like "DoEvents" in VisualBasic, I thought about CWinApp::DefWindowProc or so ?

You can't block your main application thread.  If you want your main thread to be notified that some work is done or that an event has occurred you have to post it a message or put a timer on the main thread and have it periodically test the state of an object or variable (the first method is preferred).  Don't block the thread.  It is likely that this is the core of your problem.  By blocking your thread you have shut down your application's message pump so no painting can occur.  



your answer is that what I wrote in my last comment, but still that doesn't solve my problem. I repeat:

Is there a possibility to call something like "DoEvents" in VisualBasic, I thought about CWinApp::DefWindowProc or so ?

Rather than using WaitForSingleObject() us MsgWaitForMultipleObjects().  This will involve a little more work, however.

I guess you could also use WaitForSingleObject with a short wait time in a loop.  (you are going to need a loop in either case).  In either case, when the wait terminates, if the object has not been signaled, you want to process messages until there are no more messages and then return to waiting.


Yes you can but you may not like the result.  You can use a PeekMessage loop and call TranslateMessage and DispatchMessage.  The problem is that, if your application's ordinary message loop does any other processing beyond TranslateMessage and DispatchMessage, that processing will be skipped until your PeekMessage loop terminates.  There is nearly always a better way of handling this situation than this.  Notice that, by creating such a loop, you have almost (though, admitedly, not completely) done away with any of the benifits of multithreading.  PeekMessage loops were the way things were done in Windows 3.1 to keep your application alive while background processing continued.  You will probably find that restructuring your code so that it doesn't require this loop will take a lot less time and be easier to maintain in both the short and long run.

Try do this ( suppose that you are in function of class derived from CWinThread )

 CErrorCritical theDialog;
 m_pMainWnd = &theDialog;



the problem is, that the function that detects the error and reports it is called as well  from the CWinApp as from the worker thread, so this idea won't help.

I also discovered MsgWaitForMultipleObjects() but from the documentation it seemed to me that the message loop is not processed during that. Am I wrong ?
If I'd  insert some dummy floating point calculations into the Wait...Sleep loop, would the message loop get processed then ?

on the long run I will restructure my code to clean that situation, but I guess you can imagine that this takes a couple of days and doesn't solve my short term problem.


There are two types of CWinApp threads: worker threads and user interface threads.
You say that your thread is "worker", but you want to show dialog from him, and it means that your thread must be user-interface. The difference between two types is in how to create them. There are two forms of AfxBeginThread (see help), you must use second one. And, as I have already said, before showing any window from thread you must set m_pMainWnd. If I dont mistake, in CWinThread initially m_pMainWnd pointer is NULL; so you can check for this to not to change m_pMainWnd of CWinApp object. Do like this:
bool bInThread = m_pMainWnd ? false :  { true ;m_pMainWnd = &dlg; }
if (bInThread) m_pMainWnd = NULL;
As I understood, your function is not class member, so you can pass m_pMainWnd there ( by reference )


Well, I had some time so I decided to try to replicate your problem.  I Created an app and gave the main window the DS_SYSMODAL style (somewhat dubious) and created a work thread whenever a new document was created.  In the work thread I brought up a dialog without any problem.  Perhaps you could expand on the problem or create a small simple app and see if you can replicate the problem yourself.


Hey guys,
thanks for the continued support ... I'm on weekend at home, but right on Monday I'll check out tulin's proposal. The interesting thing is that I was wrong telling that the worker thread was CWinThread derived ... this special thread isn't, it's not created with "CWinThread::CreateThread()", so this makes me hopeful of getting it done on the "tulin way".
seippg, the App is quite large, I guess 750 kB source code together, and I think it'll be easier to make the big structural change (CWinApp doesn't WAIT, this will be done by a separate thread) than filtering out the parts that are of interest.


I converted the worker thread into a real user-interface thread, calling AfxBeginThread with the RUNTIME_CLASS.

That didn't change the problem; I guess I can't avoid wrapping  the WaitForSingleObject part into an own thread.


Don't be surprised if your latest idea doesn't fix the problem.  I think it's worth a shot but, like I mentioned in my last response, I was not able to recreate the problem using the design constraints which you mentioned in your original email (i.e. I created an app and it worked just fine).  I've seen this happen before.  Someone, somewhere in the code, fiddles with some handles incorrectly or does something incorrectly with some GDI resources and something completely unrelated breaks or doesn't work.  It may be tough to track down.  Try to resist the urge to strangle the offending coder when you find it. Best of luck.




what wouldn't you  say when the Dialog comes up if the CWinApp DOESNT wait, but if it waits for the detecting thread to stop then the dialog doesn't appear ?
That's the fact in the moment, and the only clue to me is that CWinApp mustn't wait.
(Forget DS_SYSMODAL, with or without, its the same)
Unlock this solution with a free trial preview.
(No credit card required)
Get Preview



the problem is solved; I isolated the task waiting for the worker thread to terminate, wrapped a CWinThread around it and everything is fine. Yout idea with messaging is not applicable for this problem.
Nevertheless, you were the first one to lead me to examine the different threads, and you did excellent support, so you're really the one who has earned excellent 200 points.

Glad to hear.  It sounds like you've made some good and needed changes to the app as well.

Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a free trial preview!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.