CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 6 of 6
  1. #1
    Join Date
    Apr 2007
    Posts
    162

    Accessing a class 2 levels up

    The app I am writing is dialog based and the dialog class is called CDogDlg
    From this class I open another dialog using its class CRulesDialog
    Code:
    CRulesDialog *Crd;
    Crd = new CRulesDialog();
    Crd->Create(CRulesDialog::IDD,this);
    Now in the initdialog function of the new window I can access the calling class by using
    Code:
    CDogDlg *CCd;
    CCd=(CDogDlg*)GetParent();
    From the CRulesDialog class I open another window using its
    class
    Code:
    CFspFormats *Cfspf;
    Cfspf = new CFspFormats();
    Cfspf->Create(CFspFormats::IDD,this);
    In the initdialog function of this new window I can access the calling class again using
    Code:
    CRulesDialog *Crd;
    CRd=(CRulesDialog*)GetParent()
    But how do I get to the original class CDogDlg (2 levels up)????

    Thanks
    Zapper

  2. #2
    Join Date
    Mar 2008
    Location
    Turin / Italy
    Posts
    178

    Re: Accessing a class 2 levels up

    Calling GetParent()->GetParent() will get you 2 levels up. Just plase an ASSERT to be sure it works.

  3. #3
    Join Date
    Apr 2007
    Posts
    162

    Re: Accessing a class 2 levels up

    So is the syntax:

    CCd=(CDogDlg*)GetParent()->GetParent();

    because I tried that and it didn't work.

  4. #4
    Join Date
    Jan 2002
    Location
    Scaro, UK
    Posts
    5,940

    Re: Accessing a class 2 levels up

    I have to say that if you're doing this then your design is almost certainly wrong.

    Why should a window need to access its grandparent window ? In fact it shouldn't need to access its parent either. This is causing an upwards dependency between child and parent which is bad.

    I'd rethink your design - think about passing a data structure into the child windows for them to change. Then use a windows message (or even better the observer pattern) if parents need to know of changes in child windows.

    Darwen.
    www.pinvoker.com - PInvoker - the .NET PInvoke Interface Exporter for C++ Dlls.

  5. #5
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: Accessing a class 2 levels up

    Another way to approach this is to take a 'data centric' approach. That is, rather than worrying about parent/child/grandchild relationships, the child dialogs act on 'document' data.

    If the child dialogs initialize and update their data to a common document they are free to be able to be called in any order.

    See the attached sample for an MFC dialog application that displays two child dialogs with all dialogs updating their data to a common document.

    Here are the details:

    First we borrow from the MFC Doc/View architecture idea and create a simple 'Document' class:
    Code:
    class CDataDocument
    {
    public:
     CDataDocument( CString sName, CString sLocation, UINT uDistance )
      : m_sName( sName )
        , m_sLocation( sLocation )
        , m_uDistance( uDistance )
      {
      }
    
      ~CDataDocument()
      {
      }
    
    // Data accessors (used by DDX)
    public:
      CString&	 GetName( )      { return m_sName; }
      CString&	 GetLocation( )  { return m_sLocation; }
      UINT&    	 GetDistance( )  { return m_uDistance; } 	
    
    private:
      CString m_sName;
      CString m_sLocation;
      UINT     m_uDistance;
    };
    Next in the main dialog, we create a member pointer to the CDataDocument class and initialize it in the OnInitDialog override
    Code:
    BOOL CMainDlg::OnInitDialog()
    {
      // Create and initialize our 'document'
      // Since the document pointer is used in the DoDataExchange call, we
      // need to create the document before calling the base OnInitDialog( )
      m_pDataDocument = new CDataDocument( _T("Arjay"), _T("Seattle, WA"), 10 );
    
      CDialog::OnInitDialog();
    
      // Other standard initialization done here
    
      return TRUE;
    }
    For each control, add a DDX data variable of the proper type, and then modify each entry to point to the data document. (Don't forget to delete
    the each member variable in the header file because they are no longer
    used)
    Code:
    void CMainDlg::DoDataExchange(CDataExchange* pDX)
    {
      CDialog::DoDataExchange(pDX);
    
      DDX_Text(pDX, IDC_NAME, m_pDataDocument->GetName( ) );
      DDX_Text(pDX, IDC_LOCATION, m_pDataDocument->GetLocation( ) );
      DDX_Text(pDX, IDC_DISTANCE, m_pDataDocument->GetDistance( ) );
    }
    The default constructors in the child dialogs are modified to take a CDataDocument pointer (see the code for details).

    Next, Child1 and Child2 button handlers are created to display the child dialogs:
    Code:
    void CMainDlg::OnBnClickedChild1()
    {
      // Save name changes to the document
      UpdateData( TRUE );
    
      CChild1Dlg dlg( this, m_pDataDocument );;
    	
      if( IDOK == dlg.DoModal( ) )
      {
        // Update the display with document changes
        UpdateData( FALSE );
      }
    }
    
    void CMainDlg::OnBnClickedChild2()
    {
      // Save name changes to the document
      UpdateData( TRUE );
    
      CChild2Dlg dlg( this, m_pDataDocument );
    
      if( IDOK == dlg.DoModal( ) )
      {
        // Update the display with document changes
        UpdateData( FALSE );
      }
    }
    Here's what the DoDataExchange and Child2 button handler looks
    like in the Child1 dialog:
    Code:
    void CChild1Dlg::DoDataExchange(CDataExchange* pDX)
    {
      CDialog::DoDataExchange(pDX);
      DDX_Text(pDX, IDC_LOCATION, m_pDataDocument->GetLocation( ) );
    }
    
    void CChild1Dlg::OnBnClickedChild2()
    {
      CChild2Dlg dlg( this, m_pDataDocument );
      dlg.DoModal( );
    }
    The Child2 dialog changes aren't very interesting. Just DoDataExchange modification and initialize the spin control in OnInitDialog.
    Code:
    void CChild2Dlg::DoDataExchange(CDataExchange* pDX)
    {
      CDialog::DoDataExchange(pDX);
      
      DDX_Text(pDX, IDC_DISTANCE, m_pDataDocument->GetDistance( ) );
      DDX_Control(pDX, IDC_SPIN1, m_DistanceSpinCtrl);
    }
    
    // CChild2Dlg message handlers
    BOOL CChild2Dlg::OnInitDialog()
    {
      CDialog::OnInitDialog();
      
      m_DistanceSpinCtrl.SetRange32( 0, 100 );
    
      return TRUE;
    }
    You can see that using this approach and leveraging DDX, there isn't much code to write, no complicated Parent/Grandparent relationships or message passing.

    The code ends up being quite compact. P.S. You can use this same approach when working with PropertySheet/PropertyPages to really simplify things.
    Attached Images Attached Images  
    Attached Files Attached Files

  6. #6
    Join Date
    Apr 2007
    Posts
    162

    Re: Accessing a class 2 levels up

    @ Arjay

    Wow...Thats a great response man.....thanks very much

    Zapper

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured