We help IT Professionals succeed at work.

Modal Dialog

Nevering
Nevering asked
on
Medium Priority
720 Views
Last Modified: 2013-11-19
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


Comment
Watch Question

Commented:
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.

Unlock this solution and get a sample of our free trial.
(No credit card required)
UNLOCK SOLUTION
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

Author

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.
Sorry, I meant.

DDX_Text(pDX, IDC_MESSAGE, Msg);

This will definitely work. Are you sure you are going through the correct c'tor???
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.

Author

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



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

Author

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);

I think I see your problem. I need to test something. Back in a sec...
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

Author

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.

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

Author

Commented:
thanks, email to ken@ishere.com
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

Author

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


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

Please provide your email to receive a sample view!

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

OR

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.