MFC Doc/View: How to get the active document anywhere in my application?
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1

Thread: MFC Doc/View: How to get the active document anywhere in my application?

Hybrid View

  1. #1
    ovidiucucu's Avatar
    ovidiucucu is offline Moderator/Reviewer Power Poster
    Join Date
    Feb 2003
    Location
    Iasi - Romania
    Posts
    7,994

    MFC Doc/View: How to get the active document anywhere in my application?

    Q: How to get the active document anywhere in my application?

    A: There are several methods, one is to get first the active frame then call CFrameWnd::GetActiveDocument.
    In an SDI application the main frame is the main window itself so a function which gets the active document may look like:
    Code:
    CDocument* GetSDIActiveDocument()
    {
        CDocument* pDoc = NULL;
    
        CWnd* pWndMain = AfxGetMainWnd();
        ASSERT(pWndMain);
        ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)) && 
              !pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an SDI app.
        
        pDoc = ((CFrameWnd*)pWndMain)->GetActiveDocument();
    
        return pDoc;
    }
    In MDI applications, we have to additionally get the active MDI child frame.
    Code:
    CDocument* GetMDIActiveDocument()
    {
        CDocument* pDoc = NULL;
    
        CWnd* pWndMain = AfxGetMainWnd();
        ASSERT(pWndMain);
        ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an MDI app.
    
        CFrameWnd* pFrame = ((CMDIFrameWnd*)pWndMain)->MDIGetActive();
        if(NULL != pFrame)
        {
            pDoc = pFrame->GetActiveDocument(); // get the active document
        }
        return pDoc;
    }
    Putting them together we can write the following generic function to be used either in SDI or MDI applications.
    Code:
    CDocument* GenericGetActiveDocument()
    {
        CDocument* pDoc = NULL;
        CWnd* pWndMain = AfxGetMainWnd();
        if(NULL != pWndMain)
        {
            if(pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd)))
            {
                // MDI application, so first we have to get the active MDI child frame.
                CFrameWnd* pFrame = ((CMDIFrameWnd*)pWndMain)->MDIGetActive();
                if(NULL != pFrame)
                {
                    pDoc = pFrame->GetActiveDocument();
                }
            }
            else if(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
            {
                // SDI appllication so main window is the active frame. 
                pDoc = ((CFrameWnd*)pWndMain)->GetActiveDocument();
            }
            else
            {
                ASSERT(FALSE); // Neither MDI nor SDI application.
            }
        }
        return pDoc;
    }
    Before casting to a given document type we have to check if indeed the returned pointer is of that type.
    Code:
        CDocument* pDoc = GenericGetActiveDocument();
        if((NULL != pDoc) && pDoc->IsKindOf(RUNTIME_CLASS(CMyDocument)))
        {
            CMyDocument* pMyDoc = (CMyDocument*)pDoc;
            // enjoy of ponter to CMyDocument object.
        }
    To avoid such type of tests in many places, the GenericGetActiveDocument function can be improved, giving to it info about the required document type.
    Code:
    CDocument* GenericGetActiveDocument(CRuntimeClass* pClass)
    {
        ASSERT(NULL != pClass); // must be not NULL and derived from CDocument.
        ASSERT(pClass->IsDerivedFrom(RUNTIME_CLASS(CDocument))); 
    
        CDocument* pDoc = NULL;
        CWnd* pWndMain = AfxGetMainWnd();
        if(NULL != pWndMain)
        {
            if(pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd)))
            {
                // MDI application, so first we have to get the active MDI child frame.
                CFrameWnd* pFrame = ((CMDIFrameWnd*)pWndMain)->MDIGetActive();
                if(NULL != pFrame)
                {
                    CDocument* pActiveDoc = pFrame->GetActiveDocument();
                    if((NULL != pActiveDoc) && pActiveDoc->IsKindOf(pClass))
                    {
                        // The found document is of required type
                        pDoc = pActiveDoc;
                    }
                }
            }
            else if(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
            {
                // SDI appllication so main window is the active frame. 
                pDoc = ((CFrameWnd*)pWndMain)->GetActiveDocument();
            }
            else
            {
                ASSERT(FALSE); // Neither MDI nor SDI application.
            }
        }
        return pDoc;
    }
    With the help of a little macro...
    Code:
    #define GET_ACTIVE_DOC(x) (x*)GenericGetActiveDocument(RUNTIME_CLASS(x))
    ...all remained to write anywhere in the SDI/MDI MFC application is
    Code:
        CMyDocument* pDoc = GET_ACTIVE_DOC(CMyDocument);

    See also:
    Last edited by ovidiucucu; March 27th, 2009 at 06:43 AM.
    Ovidiu Cucu
    "When in Rome, do as Romans do."
    Visit: Microsoft Virtual Academy
    Follow: https://twitter.com/#!/ovidiucucu
    My blog: http://codexpert.ro/blog/author/ovidiu-cucu/

Tags for this Thread

Posting Permissions

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


Azure Activities Information Page

Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center