Solved

Main dialog, child dialog communication

Posted on 2008-10-27
18
1,153 Views
Last Modified: 2013-11-20
I am finding myself in a situation where I have a main dialog with children dialogs , such as tabs pages etc, where there is some sort of variable in the main dialog in which the children dialogs need to have access to it (not just read from it but also modify it). So what I have done for now is declare it a static member variable and the children dialog classes are friend classes of the main dialog. I don't really think this is a good approach to design since the static member variables are now stuck in memory until the program terminates. Would it be better to use thread messages between the dialogs? Or what other approaches to this problem should I consider?
0
Comment
Question by:steenpat
  • 10
  • 5
  • 3
18 Comments
 
LVL 31

Accepted Solution

by:
Zoppo earned 250 total points
ID: 22812515
Hi steenpat,

IMO you don't need to use static members. You can just use a normal member and access it via a pointer to the parent dialog, i.e.:

class CParentDlg ...
{
 public:
  int m_nMember;
 ...
};

void
CChildDlg::AnyFunction()
{
 CWnd* pWnd = GetParent();
 CParentDlg* pParent = STATIC_DOWNCAST( CParentDlg, pWnd );
 if ( NULL == pParent )
 {
  ASSERT( 0 );
  return;
 }
 pParent->m_nMember = 5;
}

BTW, it would be nicer to declare that member in CParentDlg as private and implement access to the member using getter/setter functions.

Hope that helps,

ZOPPO
0
 

Author Comment

by:steenpat
ID: 22813584
do i have to declare the parentdlg with DECLARE_DYNAMIC? .. i did this, and the dialog is crashing
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22813616
For this issue it shouldn't make a difference if the dialog is declared with DECLARE_DYNAMIC.

Where does it crash?
0
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 

Author Comment

by:steenpat
ID: 22813754
error C2039: 'classCParentDlg' : is not a member of 'CParentDlg'
(21) : see declaration of ''CParentDlg'
 : error C2065: 'classCParentDlg' : undeclared identifier

this is the error i get when i use this code
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22813777
This happens if you have no appropriate IMPLEMENT_DYNAMIC or the arguments for IMPLEMENT_DYNAMIC are wrong ...
0
 

Author Comment

by:steenpat
ID: 22813845
i am getting these compile errors without using implement dynamic..
0
 

Author Comment

by:steenpat
ID: 22813895
From MSDN:
http://msdn.microsoft.com/en-us/library/cfy5wsfk(VS.80).aspx

The class specified in the class_name parameter must be derived from CObject and must use the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC, the DECLARE_DYNCREATE and IMPLEMENT_DYNCREATE, or the DECLARE_SERIAL and IMPLEMENT_SERIAL macros as explained in the article CObject Class: Deriving a Class from CObject.
0
 

Author Comment

by:steenpat
ID: 22813901
when i use declare_dynamic and implement_dynamic there are no compile errors, but when the dialog opens it fails to display child dialogs, and crashes when i try to press next, back etc.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22813990
Did this work without problems as you tried it with static member? Where does it crash?

Maybe you call this from a dialog which is not a direct child of the parent dialog? In this case you'll have to find another way to access the parent dialog's members. I.e. you could pass a pointer to the parent dialog to all child dialogs at creation or something like this.
0
 

Author Comment

by:steenpat
ID: 22814053
"Did this work without problems as you tried it with static member? Where does it crash?"
Yes it worked without problems.

"Maybe you call this from a dialog which is not a direct child of the parent dialog?"
I'm not sure what is meant by 'direct child'. All I did was use Create in the parent dialog to create the child dialogs with second parameter of 'this' implying that this child dialog uses the main dialog as parent.
0
 
LVL 31

Expert Comment

by:Zoppo
ID: 22814154
Well, then I don't see why it's not working.

Can you put a breakpoint after the line:
> CParentDlg* pParent = STATIC_DOWNCAST( CParentDlg, pWnd );
and check in debugger if the pParent is valid (not NULL) and points to a CParentDialog?

Regards,

ZOPPO
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22815790
>>>> All I did was use Create in the parent dialog to create the child dialogs with second parameter of 'this'

Where did you create the child dialogs? The earliest time you should do that is in MainDialog::OnInitDialog after the baseclass function CDialog::OnInitDialog already was called.

Did you initialize the member you added to your dialog in the constructor?

When did you access that member in your child dialogs? Note, the GetParent function works by means of the windows handle (m_hWnd). So, the child dialogs must have a valid window attached before you can call GetParent. So, you can't do it before the OnInitDialog of the child dialogs and I would suggest to do it after calling the CDialog::OnInitDialog just to make sure that the windows properly were initialized.
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 22815901
>>>> STATIC_DOWNCAST( CParentDlg, pWnd );
I would recommend against using that macro. Though it makes a runtime check regarding the MFC class hierarchie (if the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC properly were defined)  it actually is less good and more error-prone than a C++ dynamic_cast which would check already at compile-time. So better do

   CParentDlg* pParent = dynamic_cast<CParentDlg*>(GetParent());

Again: don't forget that GetParent() couldn't be called before OnInitDialog.

If you need to access the parent's member before, you should store the parent's pointer in a member variable, which already was declared correctly as a CParentDlg* in the class header of the child dialogs.
   
0
 

Author Comment

by:steenpat
ID: 22816050
I am setting break points on the main dialog's oninitdialog, .. none of them are being tripped even though the dialog launches. when i dont use declare_dynamic none of this crap occurs. is there something special that has to be done when using declare_dynamic
0
 

Author Comment

by:steenpat
ID: 22816072
the children dialogs are not being created because theres a function in the main dialogs oninitdialog that creates them, oninitdialog is not ever being called when i declare it as dynamic.. i hate mfc
0
 

Author Comment

by:steenpat
ID: 22816115
ok
.. i got some success doing this
IMPLEMENT_DYNAMIC(CMyclass, CDialog).. instead of IMPLEMENT_DYNAMIC(CMyclass, CWnd)
i dont understand why I had to implement it like this.. doesnt CDialog derivce from CWnd anyway,.. that makes no sense
0
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 250 total points
ID: 22816193
>>>> oninitdialog is not ever being called when i declare it as dynamic.. i hate mfc
Actually, the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros is essential for some MFC functionality. It rarely makes problems cause in almost all cases it was generated by the wizard. If you experience problems you most probably have done it manually and made some mistakes ...

Create a test dialog project from scratch using MFC wizard. Check the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros in the dialog sources and place your own macros exactly at the same positions. Be aware that the IMPLEMENT_DYNAMIC macro has two arguments and make sure that you have used the parent dialog class (which is CDialog for all CDialog derived classes). In the class header be aware that after the DECLARE_DYNAMIC macro you should explicitly set the access specifier, e. g.  public:, cause the DECLARE_DYNAMIC changes that (I mean it is protected:). If using the IMPLEMENT_DYNAMIC you also *must* have a message map defined by (at least) a BEGIN_MESSAGE_MAP and a END_MESSAGE_MAP macro. Copy that from your wizard generated sample and exchange the names properly.
0
 

Author Comment

by:steenpat
ID: 22816230
yeah I never use the wizards. I am sure that is much faster, but i always end up doing it manually for one reason or another. i guess i'll give you guys half n half even tho its not much pts cause both of you are helpful. thanks.
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

815 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

11 Experts available now in Live!

Get 1:1 Help Now