Search code examples
mfcdialogreplicationedit

Replicating user input from edit control of one MFC dialog to an edit control of another dialog


In one of my dialog based MFC application, I've used two dialogs of similar look. The requirement is when user populates an edit box of one dialog with some data the same to be replicated to similar edit box of another dialog instantly. I'm trying to implement it with EN_CHANGE event of the edit control; where when any change is detected application post a message with updated data to other dialog to update the content of its own edit box. The problem is when the second dialog is setting its edit box content with the received data from first dialog, EN_CHANGE event is getting triggered from the second dialog, which is obvious, resulting in an endless back and forth message exchange. Could anybody please suggest me some solution for instant replicating user inputs between edit boxes of two MFC dialogs while keeping MFC application type as dialog based?

In my implementation both the Dialogs are CDialog derived and have the following CEdit event handler and Message handler methods:

For CScreen1 class:

void CScreen1::OnEnChangeEditUser()
{
    static CString msg;
    m_username.GetWindowText(msg);
    ::PostMessage(m_mScreen2,WM_INTER_LOGIN,10,(LPARAM)&msg); //m_mScreen2 is the HWND of 2nd dlg
}

LRESULT CScreen1::OnInterLoginMsg(WPARAM wParam, LPARAM lParam)
{
    CString *msg=(CString*)lParam;
    switch((int)wParam)
    {
        case 10: 
        m_username.SetWindowText(msg->GetString()); //m_username is CEdit Ctrl
        delete msg;
        break;
    }   
    return 0;
}  

For CScreen2 class:

void CScreen2::OnEnChangeEditUser()
{
    static CString msg;
    m_username.GetWindowText(msg);
    ::PostMessage(m_mScreen1,WM_INTER_LOGIN,10,(LPARAM)&msg); //m_mScreen1 is the HWND of 1st dlg
}

LRESULT CScreen2::OnInterLoginMsg(WPARAM wParam, LPARAM lParam)
{
    CString *msg=(CString*)lParam;
    switch((int)wParam)
    {
        case 10: 
        m_username.SetWindowText(msg->GetString()); //m_username is CEdit Ctrl
        delete msg;
        break;
    }   
    return 0;
}  

Solution

  • Simply use a boolean variable to play around. I have updated your code here.

    For CScreen1 class:

    BOOL postchanges = TRUE;  //always TRUE
    
    void CScreen1::OnEnChangeEditUser()
    {
        if (!postchanges)
            return;
    
        static CString msg;
        m_username.GetWindowText(msg);
        ::PostMessage(m_mScreen2,WM_INTER_LOGIN,10,(LPARAM)&msg); //m_mScreen2 is the HWND of 2nd dlg
    }
    
    LRESULT CScreen1::OnInterLoginMsg(WPARAM wParam, LPARAM lParam)
    {
        CString *msg=(CString*)lParam;
        switch((int)wParam)
        {
            case 10: 
            postchanges = FALSE;  // do not post msg
            m_username.SetWindowText(msg->GetString()); //m_username is CEdit Ctrl
            postchanges = TRUE;  // revert back
            delete msg;
            break;
        }   
        return 0;
    }
    

    For CScreen2 class: do the same