Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Dialogs Communication

2.77/5 (59 votes)
26 Feb 2007CPOL3 min read 1   819  
On the art of exchanging data
Screenshot - CommDlgs1.jpg Child modifying Parent modified

Introduction

We often need to communicate from one dialog to another. I will center this demonstration using two classic MFC CDialog inherited classes, each of which is modal.

And as I'm far from being partisan to writing working code first, then beautifying it, I will provide well written code to make this more accessible to readers. Please notice that I don't pretend to code perfectly, nor having THE methodology to follow. I only want to give to my readers (mostly beginners) a strong foot to understand and write code by themselves.

Without further argumentation, let's jump now into the code.

Starting point: I feel lonely, I need a child

Ok, That's a pretty far origin of the need. Anyway, the occasion is given to me then to introduce you to the characters.

CParentDlg: The parent dialog

CChildDlg: The child dialog

C++
class CParentDlg : public CDialog 
{
    CButton m_btnOpenChild;    
          //The button that will open the child dialog
    CEdit m_edtCommentText;  
          //Used to transmit a comment to the child
    CButton m_chkCaptainBlind; 
          //Same with a boolean to indicate if the captain is blind
 
public:
    CParentDlg();
 
protected:
    afx_msg void OnOpenChild();  
          //Even Handler of the m_btnOpenChild button click
};

class CChildDlg : public CDialog 
{
    CEdit   m_edtCommentText;    //The comment received
    CButton m_chkCaptainBlind;   //And the boolean received
    CString m_strComment;
    bool    m_bIsCaptainBlind;
 
public:
    CChildDlg(const CString& strComment, bool bIsCaptainBlind);
    const CString& GetComment() const;
    bool IsCaptainBlind() const;
 
protected:
    virtual BOOL OnInitDialog(); 
          //Used to initialize the controls before the dialog
          // is displayed at its first time afx_msg void OnOK();
    afx_msg void OnOK();         
          //Even  Handler of the OK button click
};

Note that the class declarations are lightened to show only the important points. Due to this, the IDD enumerator, DoDataExchange(), OnQueryDragIcon(), OnSysCommand(), OnPaint() and DECLARE_MESSAGE_MAP() are implemented but hidden here. However, I keep the OnInitDialog() present because it will soon play a major role; as much as the class constructors.

Now we can open the child dialog when the button is pressed on the parent.

C++
void CParentDlg::OnOpenChild() 
{
    CString strComment;
    m_edtCommentText.GetWindowText(strComment);
    bool bIsCaptainBlind = m_chkCaptainBlind.GetCheck();
 
    CChildDlg dlg(strComment, bIsCaptainBlind);
    INT_PTR nResponse = dlg.DoModal();
    if (nResponse == IDOK) 
    {
        m_edtCommentText.SetWindowText(dlg.GetComment());
        m_chkCaptainBlind.SetCheck(dlg.IsCaptainBlind());
    }
}

In brief, the function firstly gets the content of the EditBox and the state of the CheckBox. Once these pieces of information are collected, we pass them to the child dialog and display it. The child is now responsible for the integrity of the data. In our example, the Parent will get the values since the child is left with OK, otherwise, nothing more is done.

Oh sweet baby, now we can talk

Notice the two important lines in the OnOpenChild() function above: the calling of the constructor of the child, and the start of the actual display with DoModal().

Let's detail what's happening here.

Construction: giving the information

You have certainly noticed the parameters in the contructor call. Here is how we could have defined the child dialog:

C++
CChildDlg::CChildDlg(const CString& strComment, bool bIsCaptainBlind) 
{
    this->m_strComment = strComment;
    this->m_bIsCaptainBlind = bIsCaptainBlind;
}

Now we have the data stored in the child dialog class. But we still have to display them properly.

Display: showing the information

We don't directly code the DoModal() function. This one is inherited from the CDialog class and we don't need to know what it does except the fact that it constructs a modal dialog box, executing in this process our OnInitDialog():

C++
BOOL CChildDlg::OnInitDialog() 
{
    CDialog::OnInitDialog();
    m_edtCommentText.SetWindowText(m_strComment);
    m_chkCaptainBlind.SetCheck(m_bIsCaptainBlind);
    return TRUE;
}

Let the user play, and give me feedback when he's gone

For us (as developers), there is nothing much to do other than to wait.

The child dialog has been constructed, initialized, then displayed. The user is now playing with the UI, modifying our initial comment and checking/unchecking our CheckBox.

One could have added some event handlers, but that's not the point here. We're only covering the communication between the parent and its child.

We then wait until the child is closed. Here, there are two possibilities of doing so: Validating the changes made by OK, or cancelling (with the button of the same name).

Here, I choose to let the user change what he wants, and only if OK is pressed, the two data members are updated. For this, I added an event handler on the OK button.

C++
void CChildDlg::OnOK() 
{
    m_edtCommentText.GetWindowText(m_strComment);
    m_bIsCaptainBlind = m_chkCaptainBlind.GetCheck();
    EndDialog(IDOK);
}

Why do we need this? Because it is the content of those members that the parent will recover using GetComment() and IsCaptainBlind() accessors.

Here dad, your data

Let's jump back to the end of OnOpenChild() parent handler:

C++
if (nResponse == IDOK) 
{
    m_edtCommentText.SetWindowText(dlg.GetComment());
    m_chkCaptainBlind.SetCheck(dlg.IsCaptainBlind());
}

When the button OK is pressed, we now get into the if statement, and finally update the parent UI.

Summary

That was a pretty light example. In the real world, you will often need to exchange a lot of data depending on the case.

What is usually done is encapsulating all the data that needs to be exchanged into a class defined for it, and transmiting a single instance of that class.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)