Solved

C++, MFC: Supplying constructor arguments to a CDialog derived class correctly

Posted on 2007-11-20
17
2,032 Views
Last Modified: 2013-12-14
Hello,

I would like to supply a constructor argument to a wizard-generated CDialog derived class in MFC. This is the natural way to do it, because the dialog's content is predicated on a single seed value (an integer).

CMyDialog TheDialog(5); // TheDialog is instantiated

I see that wizard generated code for CDialog derived classed supplies a constructor like this:

CMyDialog ::CMyDialog (CWnd* pParent /*=NULL*/)
      : CDialog(CMyDialog ::IDD, pParent)
{

}

I would like to instantiate this variable as above, with a particular class member integer's value initiated as described.

This:


CMyDialog::CMyDialog (CWnd* pParent /*=NULL*/,int sku_is)
      : CDialog(CEditExistingProductDialog::IDD, pParent)

{
      sku = sku_is; // sku is the class member

}

causes an assertion failure when I supply CWnd* pParent as "this" (from anothe CDialog derived class), or if I supply NULL.

How should I go about getting this thing to work as described?

Regards,
Sternocera
0
Comment
Question by:sternocera
  • 3
  • 3
  • 3
  • +6
17 Comments
 
LVL 40

Accepted Solution

by:
evilrix earned 168 total points
ID: 20321586
So, you added the new constructor param, it built ok but then after that you get the assertion? And if you revert the code I presume the assertion goes away?

Do you now have both constructors or just your new version?

BTW: Prefer to use constructor initialization lists -- they are more efficient...

CMyDialog::CMyDialog (CWnd* pParent /*=NULL*/,int sku_is)
      : CDialog(CEditExistingProductDialog::IDD, pParent), sku(sku_is)

{
}
0
 
LVL 55

Assisted Solution

by:Jaime Olivares
Jaime Olivares earned 166 total points
ID: 20321660
Will be less confusing if you have just one constructor like:

prototype:
      CMyDialog (int sku_is, CWnd* pParent =NULL);

implementation:
CMyDialog::CMyDialog (int sku_is, CWnd* pParent /*=NULL*/)
      : CDialog(CEditExistingProductDialog::IDD, pParent)

{
      sku = sku_is; // sku is the class member
}

notice the order in arguments in constructor
0
 
LVL 11

Expert Comment

by:DeepuAbrahamK
ID: 20321965

When you give defualt arguments, the default arguments should be placed in the right most parameter
Have a look at this:
http://web.mit.edu/merolish/ticpp/Chapter07.html
Best Regards,
DeepuAbrahamK
0
 
LVL 4

Expert Comment

by:yuy2002
ID: 20325948
In header file, you should decalre CMyDialog construct fuction with the second parameter initialized.

class CMyDialog : public CDialog
{
// Construction
public:
      CMyDialog (CWnd* pParent = NULL,int sku_is = 0);      // standard constructor
...
}
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20326192
>> In header file, you should decalre CMyDialog construct fuction with the second parameter initialized.
Um, why? That is only useful if it valid to have sku_is with a default value of 0.
0
 

Author Comment

by:sternocera
ID: 20326813
Any variation on the default wizard generated constructor doesn't seem to do what's expected.

CMyDialog (int sku_is, CWnd* pParent =NULL);

doesn't work any better then:

CMyDialog (CWnd* pParent =NULL, int sku_is);

I've decided that it's more trouble then it's worth; I've just made the variable public and explicitly modified it before I call the dialog's DoModal().

Thanks.



0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20326848
>>>> causes an assertion failure when I supply CWnd* pParent as "this"
>>>>  (from anothe CDialog derived class), or if I supply NULL.

I would assume that you do more than

        sku = sku_is; // sku is the class member

in the constructor. Or you try to create the dialog in the constructor of the other dialog class. Break into the debugger and examine the call stack when the assertion comes. Most likely it says that the m_hWnd is invalid for your current dialog or the parent dialog. That is not astonishing if you have not created a window for the dialog until then. You can't use a dialog CWnd pointer prior to the WM_INIT_DIALOG message which was issued after CDialog::Create and was handled in CYourDialog::OnInitDialog.  

So, the normal thing is that you have some button in your first dialog. When it is clicked you will have a handler function like that:

void MyFirstDialog::OnBtnClickedStartSecondDialog()
{
       CMyDialog mydlg(this, 123);   // 123 is sku_is
       mydlg.DoModal();
}

Note, here you can use the 'this' as the first dialog already was created and has a valid windows handle. The DoModal will create your second dialog window and make a modal dialog.

Regards, Alex
0
 
LVL 40

Expert Comment

by:evilrix
ID: 20326849
I tried doing this this morning without any problems. I'm wondering if the problem isn't actually this bit of code but somewhere else. Maybe, if it's not a big project, you could upload it to http://www.ee-stuff.com/ so we can have a look at it for you?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20326872
Note, for any change you make you *have to* make a rebuild cause the 'precompiled header' must be recreated. In some versions of Visual Studio (or when working with a versioning system) the PCH was not automatically rebuilt waht may cause very strange errors and assertions (like the ones you posted).
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 20327439
IMHO the initial suggestion by Jaime is the way to achieve what you want and should work without any problems.

ps.
Make certain the original declaration isn't still there in the header and .cpp file :-
CMyDialog (CWnd* pParent /*=NULL*/)

otherwise you might actually be calling that somewhere instead of your customised one.
0
 

Author Comment

by:sternocera
ID: 20327459
interface arguments are consistent with implementation arguments, that's not it.

It seems counter-intuitive to me too, but it is so.


Thanks,
Sternocera
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 20327609
Can you post the function where you were using the CMyDialog constructor? And where the assertion pops up? Can you post the current call stack then?
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 20327823
ps.

I hope you don't have code like this

CDlg1 dlg1;
dlg1.DoModal();

CDlg2 dlg2(42, &dlg1);   <<----  Assuming CDlg1 requires and int and a CWnd pointer in that order
At this point dlg1 as a WINDOW does not exist any more
0
 

Author Comment

by:sternocera
ID: 20327843
No, I appreciate that  CDlg1 would cease to exist,
Regards,
Sternocera
0
 
LVL 49

Assisted Solution

by:DanRollins
DanRollins earned 166 total points
ID: 20356425
I find it best to avoid tinkering with the wizard-generated ctors, especially in the case described because...

The normal way to "pass a value" into a CDialog-derive object is to provide a member variable and assign it a value before using DoModal() or Create().  E.g.:

CDlg1 dlg1;
dlg1.m_sku= 5;
dlg1.DoModal();

Then take action (that needs the m_sku value) in on the OnInitDialog()
0
 
LVL 1

Expert Comment

by:Computer101
ID: 21026318
Forced accept.

Computer101
EE Admin
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
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.

757 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

19 Experts available now in Live!

Get 1:1 Help Now