Solved

Modal Dialog

Posted on 1998-06-01
16
676 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


0
Comment
Question by:Nevering
  • 9
  • 6
16 Comments
 

Expert Comment

by:t004024
ID: 1315910
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
 
LVL 3

Accepted Solution

by:
tma050898 earned 50 total points
ID: 1315911
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315912
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
 
LVL 1

Author Comment

by:Nevering
ID: 1315913
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315914
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315915
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
 
LVL 1

Author Comment

by:Nevering
ID: 1315916
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315917
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 1

Author Comment

by:Nevering
ID: 1315918
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315919
I think I see your problem. I need to test something. Back in a sec...
0
 
LVL 3

Expert Comment

by:tma050898
ID: 1315920
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
 
LVL 1

Author Comment

by:Nevering
ID: 1315921
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
 
LVL 3

Expert Comment

by:tma050898
ID: 1315922
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
 
LVL 1

Author Comment

by:Nevering
ID: 1315923
thanks, email to ken@ishere.com
0
 
LVL 3

Expert Comment

by:tma050898
ID: 1315924
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
 
LVL 1

Author Comment

by:Nevering
ID: 1315925
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

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

This is to be the first in a series of articles demonstrating the development of a complete windows based application using the MFC classes.  I’ll try to keep each article focused on one (or a couple) of the tasks that one may meet.   Introductio…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now