[MFC] Cum obtin view-ul activ oriunde intr-o 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 obtin view-ul activ oriunde intr-o aplicatie?

Post by Ovidiu Cucu » 20 Oct 2010, 14:36

Intrebare: Cum pot obtine view-ul 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::GetActiveView.

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

Code: Select all

CView* GetSDIActiveView()
{
    CView* pView = NULL;

    CWnd* pWndMain = AfxGetMainWnd();
    ASSERT(pWndMain);
    ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)) && 
          !pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an SDI app.
    
    pView = ((CFrameWnd*)pWndMain)->GetActiveView(); // get the active view

    return pView;
}
In aplicatiile MDI (Multiple Document Interface) trebuie in plus ca sa gasesc frame-ul copil activ (active MDI child frame).

Code: Select all

CView* GetMDIActiveView()
{
    CView* pView = NULL;

    CWnd* pWndMain = AfxGetMainWnd();
    ASSERT(pWndMain);
    ASSERT(pWndMain->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd))); // Not an MDI app.

    CFrameWnd* pFrame = ((CMDIFrameWnd*)pWndMain)->MDIGetActive();
    if(NULL != pFrame)
    {
        pView = pFrame->GetActiveView(); // get the active view
    }
    return pView;
}
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

CView* GenericGetActiveView()
{
    CView* pView = 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)
            {
                pView = pFrame->GetActiveView();
            }
        }
        else if(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
        {
            // SDI appllication so main window is the active frame. 
            pView = ((CFrameWnd*)pWndMain)->GetActiveView();
        }
        else
        {
            ASSERT(FALSE); // Neither MDI nor SDI application.
        }
    }
    return pView;
}
Inainte de a face conversie (cast) la un view de un anumit tip, trebuie verificat daca intradevar pointerul returnat este de acel tip.

Code: Select all

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

Code: Select all

CView* GenericGetActiveView(CRuntimeClass* pClass)
{
    ASSERT(NULL != pClass); // must be not NULL and derived from CView.
    ASSERT(pClass->IsDerivedFrom(RUNTIME_CLASS(CView))); 

    CView* pView = 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)
            {
                CView* pActiveView = pFrame->GetActiveView();
                if((NULL != pActiveView) && pActiveView->IsKindOf(pClass))
                {
                    // The found document is of required type
                    pView = pActiveView;
                }
            }
        }
        else if(pWndMain->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
        {
            // SDI appllication so main window is the active frame. 
            pView = ((CFrameWnd*)pWndMain)->GetActiveView();
        }
        else
        {
            ASSERT(FALSE); // Neither MDI nor SDI application.
        }
    }
    return pView;
}
Cu ajutorul unui mic macro...

Code: Select all

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

Code: Select all

    CMyView* pMyView = GET_ACTIVE_VIEW(CMyView);
Vezi de asemenea: << Back to MFC index



Post Reply