Modal Dialog

Here's a MFC newbie question.  I'm having touble updating a CStatic in a message dialog.  I've created  a new Class based on CDialog named CWaitDialog. I'm passing in a message and would like the message to display when the dialog comes up.  The dialog box is empty upon passing in the string "Please wait. processing.."
I have tried m_Msg.SetWindowText in the constructor and it has an assertion error.  I then tried it in OnInitDialog, and no problems, but it doesn't appear.  Here is the code.



#if !defined(AFX_WAITDIALOG_H__C88EFCC2_F55E_11D1_AA23_006008A95177__INCLUDED_)
#define AFX_WAITDIALOG_H__C88EFCC2_F55E_11D1_AA23_006008A95177__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// WaitDialog.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog dialog

class CWaitDialog : public CDialog
{
// Construction
public:
      CWaitDialog(LPCSTR msg, CWnd* pParent = NULL);   // standard constructor

// Dialog Data
      //{{AFX_DATA(CWaitDialog)
      enum { IDD = IDD_WAITDIALOG };
      CStatic      m_Msg;
      //}}AFX_DATA


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

// Implementation
protected:
      CString Msg;

      // Generated message map functions
      //{{AFX_MSG(CWaitDialog)

      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_WAITDIALOG_H__C88EFCC2_F55E_11D1_AA23_006008A95177__INCLUDED_)



// WaitDialog.cpp : implementation file
//

#include "stdafx.h"
#include "impro.h"
#include "WaitDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog dialog


CWaitDialog::CWaitDialog(LPCSTR msg, CWnd* pParent/*=NULL*/)
      : CDialog(CWaitDialog::IDD, pParent)
{
      //{{AFX_DATA_INIT(CWaitDialog)
            // NOTE: the ClassWizard will add member initialization here
      //}}AFX_DATA_INIT
      Msg = msg;
}


void CWaitDialog::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CWaitDialog)
      DDX_Control(pDX, IDC_MESSAGE, m_Msg);
      //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CWaitDialog, CDialog)
      //{{AFX_MSG_MAP(CWaitDialog)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog message handlers


LVL 1
NeveringAsked:
Who is Participating?
 
tma050898Connect With a Mentor Commented:
You have a CStatic called m_Msg and a CString called Msg. You set Msg to a value in the dlg's c'tor. So far no, problem. HOWEVER, Msg is not associated with the control IDC_MESSAGE. You associated m_Msg with that control, but not Msg. Therefore, you can do a couple of things.

1. You can add the following line to your DoDataExchange
DDX_Text(pDC, IDC_MESSAGE, m_Msg);

2. *OR* you can place the following in your OnInitDialog
m_Msg.SetWindowText("whatever");

Tom

0
 
t004024Commented:
U cannot create a m_Msg as a CString and just set it, since the data is transfered only when the DoDataExchange is called and it is not called when initializing. U have to put the SetWindowText code in the OnInitDialog, because, the control is not created till then. But it does not display the text since U are not forcing windows to update itself. Since it is a non modal dialog, it just posts the message in the queue and continues on with the rest of the code and the update of the dialog box is done only when the processor has finished it's work, which is when U'll be closing the dialog. So try calling m_Msg.UpdateWindow() after SetWindowText(), to force an update.

0
 
tma050898Commented:
BTW, t004024 stated that "U cannot create a m_Msg as a CString and just set it, since the data is transfered only when the DoDataExchange is called and it is not called when initializing."

This is only partially true. Yes, data is only transfered when DoDataExchange is called. However, DoDataExchange is called in the CDialog::OnInitDialog. Actually, UpdateData is called, but the point is that your DoDataExchange function will eventually be called when the dialog is initialized unless you explicity override OnInitDialog and don't call the base class' implementation.

Therefore, if you initialize Msg in the c'tor, the value will be moved to the IDC_MESSAGE control when CDialog::OnInitDialog is called.

Tom

0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

 
NeveringAuthor Commented:
tma

Your answer seems like it should work, however after trying your suggestion i get the following error message:
:\Program Files\DevStudio\MyProjects\Impro\WaitDialog.cpp(31) : error C2665: 'DDX_Text' : none of the 11 overloads can convert parameter 3 from type 'class CStatic'
Error executing cl.exe.

when doing the following

DDX_Text(pDX, IDC_MESSAGE, m_Msg);

I also tried replacing m_Msg with Msg since online help showed DDX_TEXT took a CString, however this compiled but did not produce any text in the dialog box.
0
 
tma050898Commented:
Sorry, I meant.

DDX_Text(pDX, IDC_MESSAGE, Msg);

This will definitely work. Are you sure you are going through the correct c'tor???
0
 
tma050898Commented:
Try setting a breakpoint in the constructor on the line in the c'tor that reads ...

Msg = msg;

Verify that msg is what you want it should be.

0
 
NeveringAuthor Commented:
Msg is getting set to "Please wait, rescaling form.." just fine.  I added your change, but I still don't see any change in the dialog text ????




// WaitDialog.cpp : implementation file
//

#include "stdafx.h"
#include "impro.h"
#include "WaitDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog dialog


CWaitDialog::CWaitDialog(LPCSTR msg, CWnd* pParent/*=NULL*/)
      : CDialog(CWaitDialog::IDD, pParent)
{
      //{{AFX_DATA_INIT(CWaitDialog)
      //}}AFX_DATA_INIT
      Msg = msg;
}


void CWaitDialog::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CWaitDialog)
      DDX_Text(pDX, IDC_MESSAGE, Msg);
      //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CWaitDialog, CDialog)
      //{{AFX_MSG_MAP(CWaitDialog)
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog message handlers



0
 
tma050898Commented:
Nevering,

I have NO IDEA what to tell you. Here's what I just did.

1. Created an SDI project called Nevering

2. Created a dialog (IDD_WAIT) that included a static (IDC_MESSAGE)

3. Created a class called CWaitDialog (based on IDD_WAIT)

4. Added a CString (called Msg) to the dialog's class

5. Added overloaded c'tor
 CWaitDialog::CWaitDialog(LPCTSTR msg, CWnd* pParent /*=NULL*/)
  : CDialog(CWaitDialog::IDD, pParent)
 {
  //{{AFX_DATA_INIT(CWaitDialog)
  Msg = msg;
  //}}AFX_DATA_INIT
 }

5. Changed dialog's DoDataExchange
 void CWaitDialog::DoDataExchange(CDataExchange* pDX)
 {
  CDialog::DoDataExchange(pDX);
  //{{AFX_DATA_MAP(CWaitDialog)
  DDX_Text(pDX, IDC_MESSAGE, Msg);
  //}}AFX_DATA_MAP
 }

6. Added a menu to IDR_MAINFRAME called Wait

7. Added a menu handler to the mainframe
 void CMainFrame::OnWait()
 {
  CWaitDialog dlg("Hello");
  dlg.DoModal();
 }

8. I ran it and it works perfectly!

Then, I deleted all of my dialog code and copied and pasted your code into my WaitDialog.cpp file. The only changes I had to make were to comment out your include of "impro.h", add the include of "resource.h" and remove the dialog c'tor for the dialog that CW creates automatically. I built it and once again, it works!

Sorry, but I have no idea what problems you are having. I even tried making the dialog modeless, but that had no effect.

I just went back and copied and pasted your header file over mine and as you can probably guess, it continues to work.

At this point, the only thing I can suggest is that I either send you what I have or vice versa.

Tom

0
 
NeveringAuthor Commented:
Ok, I tried it again doing a Modal like you had in your code and it worked fine.  However, I was trying to do a modeless dialog, and suspect that the problem has to do with how I'm creating the dialog.  Perhaps you can take a look at the code that I have for the modeless and see a problem?

This is your code for Modal and it worked fine.

      CWaitDialog dlg("Rescaling form, Please wait...");
      dlg.DoModal();


This is my modeless and it doesn't work??

      CWaitDialog waitDlg("Rescaling form, Please wait...", this);
      waitDlg.Create(IDD_WAITDIALOG, this);
      waitDlg.ShowWindow(SW_SHOW);

0
 
tma050898Commented:
I think I see your problem. I need to test something. Back in a sec...
0
 
tma050898Commented:
I have no idea how your code can possibly work. Your creating a modeless dialog object on the stack. That means that once the function that instantiated the dialog object ends, the dialog object will go out of scope.

An example of creating a modeless dialog would be a menu option that is handled from the mainframe. You could allocate the dialog object in the mainframe's c'tor.
 m_pDialog = new CWaitDialog("text");

Display it when needed
 if (!m_pDialog->GetSafeHwnd())
 {
  m_pDialog->Create(IDD_WAITDIALOG); // displays the  modeless dialog  
  m_pDialog->ShowWindow(SW_SHOW);
 }

And delete it in the d'tor or OnDestroy
 delete m_pDialog

HTH,
Tom

0
 
NeveringAuthor Commented:
This is just too strange....   I think the reason that it works on the stack is that I'm creating and and closing in the same block of code.  I have a function that opens the wait dialog.  Does some stuff then returns and then the dialog box should go away.

I tried your method of using new (on the heap) and no difference.  I'm confused.

0
 
tma050898Commented:
This is definitely one problem where this forum is not getting your problem solved. At this rate, we won't have this damn thing fixed for a year <G>. Seriously, if you want, give me your email and I'll email you the modeless version of the test app I have working. That way maybe you can see some reason that your version isn't working.

Tom

0
 
NeveringAuthor Commented:
thanks, email to ken@ishere.com
0
 
tma050898Commented:
I sent you the file, but I don't think it's necessary anymore. I think your problem has to do with the fact that you are creating a modeless dialog, displaying it and then doing something that isn't giving the dialog a chance to paint.

Add the following line after the ShowWindow and BEFORE the code that the end-user is waiting for the completion of.
 waitDlg.UpdateWindow();

BTW, now you can go back to creating the dialog on the stack.

HTH,
Tom

0
 
NeveringAuthor Commented:
Here is how I did mine.

Where called

      CWaitDialog waitDlg(this, &c);
      waitDlg.Create(IDD_WAITDIALOG, this);
      waitDlg.ShowWindow(SW_SHOW);
.
later

      waitDlg.DestroyWindow();


#if !defined(AFX_WAITDIALOG_H__63151CC2_FA0A_11D1_AA23_006008A95177__INCLUDED_)
#define AFX_WAITDIALOG_H__63151CC2_FA0A_11D1_AA23_006008A95177__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// WaitDialog.h : header file
//

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog dialog

class CWaitDialog : public CDialog
{
// Construction
public:
      CWaitDialog(LPCTSTR msg, CWnd* pParent = NULL);   // standard constructor

// Dialog Data
      //{{AFX_DATA(CWaitDialog)
      enum { IDD = IDD_WAITDIALOG };
      CString      m_Msg;
      //}}AFX_DATA


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

// Implementation
protected:

      // Generated message map functions
      //{{AFX_MSG(CWaitDialog)
            // NOTE: the ClassWizard will add member functions here
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Developer Studio will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_WAITDIALOG_H__63151CC2_FA0A_11D1_AA23_006008A95177__INCLUDED_)

Implementation

// WaitDialog.cpp : implementation file
//

#include "stdafx.h"
#include "impro.h"
#include "WaitDialog.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog dialog


CWaitDialog::CWaitDialog(LPCTSTR msg, CWnd* pParent /*=NULL*/)
      : CDialog(CWaitDialog::IDD, pParent)
{
      //{{AFX_DATA_INIT(CWaitDialog)
      m_Msg = msg;
      //}}AFX_DATA_INIT
}


void CWaitDialog::DoDataExchange(CDataExchange* pDX)
{
      CDialog::DoDataExchange(pDX);
      //{{AFX_DATA_MAP(CWaitDialog)
      DDX_Text(pDX, IDC_MESSAGE, m_Msg);
      //}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CWaitDialog, CDialog)
      //{{AFX_MSG_MAP(CWaitDialog)
            // NOTE: the ClassWizard will add message map macros here
      //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CWaitDialog message handlers


0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.