[MFC] Cum pot obtine documentul activ oriunde in aplicatie?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Cum pot obtine documentul activ oriunde in aplicatie?

Post by Ovidiu Cucu » 29 Mar 2009, 11:12

Intrebare: Cum pot obtine documentul activ oriunde intr-o aplicatie MFC?

Raspuns: Sunt mai multe metode, una dintre ele este sa obtinem mai intai frame-ul activ si apoi sa apelam CFrameWnd::GetActiveDocument.

Intr-o aplicatie SDI (Single Document Interface) frame-ul activ este chiar fereastra principala deci o functie care sa dea documentul activ ar putea arata cam asa:

Code: Select all

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 aplicatiile MDI (Multiple Document Interface) trebuie in plus ca sa gasesc frame-ul copil activ (active MDI child frame).

Code: Select all

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;
}
Punandu-le la un loc, putem scrie urmatoarea functie ce poate fi utilizata atat in aplicatii SDI cat si in cele MDI.

Code: Select all

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;
}
Inainte de a face conversie (cast) la un document de un anumit tip, trebuie verificat daca intradevar pointerul returnat este de acel tip.

Code: Select all

    CDocument* pDoc = GenericGetActiveDocument();
    if((NULL != pDoc) && pDoc->IsKindOf(RUNTIME_CLASS(CMyDocument)))
    {
        CMyDocument* pMyDoc = (CMyDocument*)pDoc;
        // enjoy of ponter to CMyDocument object.
    }
Pentru a evita asemenea teste in multe locuri, functia GenericGetActiveDocument poate fi imbunatatita dandu-i informatii despre tipul de document cerut (printr-un pointer la o stuctura de tip CRuntimaClass).

Code: Select all

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;
}
Cu ajutorul unui mic macro...

Code: Select all

#define GET_ACTIVE_DOC(x) (x*)GenericGetActiveDocument(RUNTIME_CLASS(x))
...tot ce a mai ramas de scris, oriunde intr-o aplicatie MFC SDI sau MDI este

Code: Select all

    CMyDocument* pDoc = GET_ACTIVE_DOC(CMyDocument);
Vezi de asemenea:
Next FAQ >>



Post Reply