CFormView



  • Hallo

    Ich habe eine Anwendung deren Ansichtsklasse von CFormview abgeleitet ist.
    In die Anwendung habe ich nun mehrere FormView-Resource eingefügt.
    wie kann man jetzt über einen Menüpunkt (CMainFrame) das aktuell angezeigte CFormView ändern.

    Danke 🙂



  • BOOL CClassBuilderDoc::SwitchToView(CRuntimeClass *pNewViewClass)
    {
    
        CMainFrame* pMainWnd = (CMainFrame*)AfxGetMainWnd();
        CView* pOldActiveView = pMainWnd->GetActiveView();
    
        // If we're already displaying this kind of view, no need to go further.
        if (pOldActiveView->IsKindOf(pNewViewClass))
            return TRUE;
    
        CSplitterWnd* pSplitter = (CSplitterWnd *)pOldActiveView->GetParent();
        pOldActiveView = (CView*)pSplitter->GetPane(0,1);//damit er nicht den Falschen View Löscht
        int row= 0, col= 1;
        ASSERT(pSplitter->IsChildPane(pOldActiveView, row, col));
        CRect viewrect;
        pOldActiveView->GetWindowRect(&viewrect);
    
        // set flag so that document will not be deleted when view is destroyed
        m_bAutoDelete = FALSE;    
        // Delete existing view 
        pOldActiveView->DestroyWindow();
        // set flag back to default 
        m_bAutoDelete = TRUE;
    //  row = 0;
    //  col = 1;
        // Create new view                      
        CCreateContext context;
        context.m_pNewViewClass = pNewViewClass;
        context.m_pCurrentDoc = this;
        context.m_pNewDocTemplate = this->GetDocTemplate();
        context.m_pLastView = pOldActiveView;
        context.m_pCurrentFrame =NULL;// pMainWnd->GetActiveFrame();
        if (!pSplitter->CreateView(row, col, pNewViewClass, viewrect.Size(), &context))
            return FALSE;
    
        // Set active 
        CMainView* pNewView = (CMainView *)pSplitter->GetPane(row, col);
        pSplitter->GetParentFrame()->SetActiveView(pNewView);
    
        pSplitter->RecalcLayout(); 
        pNewView->SendMessage(WM_PAINT); 
        return TRUE;
    }
    

    Viel Spass.

    Devil



  • Vielen Dank.
    Nur der Spass ist bisher leider ausgeblieben.
    Hab jetzt schon ziehmlcih viel versucht, aber es gibt immer Fehler.

    Hast du nicht eine Beispielanwendung, wo das funktioniert, die du mir evt. mailen könntest.

    Danke 🙂



  • Ich klinke mich mal nochmal ein...

    @devil81

    Du hast mir diesen Code auch letztens gepostet und ich bin erst am WE dazu gekommen, es auszuprobieren - klappt bei mir leider auch nicht.

    Wäre wirklich super, wenn Du mal ein Beispiel der Anwendung zeigen könntest oder mal genauer beschreibst, wo muss die Fkt genau hin, wie erfolgt ein Aufruf des Wechsels.

    Wäre super nett...
    Chris



  • Leutz, ihr müsst auch mal nen kurzen Blick in den Code werfen und möglicherweise eurem Problem anpassen. Da ihr keinen Code gepostet habt, ist es natürlich net möglich, eine für euch angepasste Funktion hier zu posten.
    Prinzipiell ist doch aber ersichtlich, dass der Code nur mit SplitterWnds funzt und man die betreffenden Zeilen ändern je nach eigenem Problem (SDI/MDI) anpassen muss.



  • Undank ist der Welten Lohn 😉

    Natürlich hab ich den Code vorher nicht so anpassen können, das er bei euch
    sofort funktioniert, da ich euer genaues Problem leider nicht kenne.
    Wie RenéG schon feststellte ist der Code für ein Splitterwindow, und müsste
    also für SDI/MDI noch von euch angepasst werden. Hoffe das überfordert euch nicht...

    Devil



  • Habs so gelöst:
    Vielleicht wäre es was für die FAQ:

    1. Eine neue FormView erstellen, (abgeleitet natürlich von CFormView)
      2)Die C.:App wird wie folgt erweitert:
    #define NUMVIEWS 3
    
    class C..App : public CWinApp
    {
    //......
    protected:
        CView * m_pViews[NUMVIEWS];
        UINT m_nCurView;
    
    1. In der Methode InitInstance() der C..App Klasse
    // Verteilung der in der Befehlszeile angegebenen Befehle
    if (!ProcessShellCommand(cmdInfo))
    return FALSE;
    
        m_nCurView = 0;        
        CView* pActiveView = ((CFrameWnd*) m_pMainWnd)->GetActiveView();
    
        m_pViews[0] = pActiveView;
        m_pViews[1] = (CView*) new NewView;  //<- hier das neu erstellte View
        m_pViews[2] = (CView*) new COriView;//<- hier das vom Assi erstelle View
    
        CDocument* pCurrentDoc =
         ((CFrameWnd*) m_pMainWnd)->GetActiveDocument();
    
        CCreateContext newContext;
        newContext.m_pNewViewClass = NULL;
        newContext.m_pNewDocTemplate = NULL;
        newContext.m_pLastView = NULL;
        newContext.m_pCurrentFrame = NULL;
        newContext.m_pCurrentDoc = pCurrentDoc;
    
        UINT viewID[3];
        viewID[1] = AFX_IDW_PANE_FIRST + 1;
        viewID[2] = AFX_IDW_PANE_FIRST + 2;    
        CRect rect(0, 0, 0, 0); // gets resized later
    
        for ( int nView=1; nView<NUMVIEWS; nView++ )
        {
            m_pViews[nView]->Create(NULL, NULL,
                    (AFX_WS_DEFAULT_VIEW & ~WS_VISIBLE),
                            rect, m_pMainWnd,
                    viewID[nView], &newContext);
        }
    
        ((NewView*)m_pViews[1])->OnInitialUpdate();//OnInitialUpdate müsst Ihr natürlich erstellen
    
        ((COriView*)m_pViews[2])->OnInitialUpdate();
    
        // Das einzige Fenster ist initialisiert und kann jetzt angezeigt und aktualisiert werden.
        m_pMainWnd->ShowWindow(SW_SHOW);
        m_pMainWnd->UpdateWindow();
    
    1. Jetzt die Konstruktoren und Destruktoren beider View Klassen auf public setzen
    2. Die OnInitialUpdate ebenfalls auf public
    3. in der C..App neue Funktion erstellen: (SwitchView(UINT nIndex))
    CView* C..App::SwitchView(UINT nIndex)
    {
            ASSERT( nIndex >=0 && nIndex < NUMVIEWS );
    
        CView* pNewView = m_pViews[nIndex];
    
        CView* pActiveView =
        ((CFrameWnd*) m_pMainWnd)->GetActiveView();
    
        if ( !pActiveView )    // No currently active view
            return NULL;
    
        if ( pNewView == pActiveView )    // Already there
            return pActiveView;
    
        m_nCurView = nIndex;    // Store the new current view's index
    
        // exchange view window ID's so RecalcLayout() works
        UINT temp = ::GetWindowLong(pActiveView->m_hWnd, GWL_ID);
        ::SetWindowLong(pActiveView->m_hWnd, GWL_ID,
              ::GetWindowLong(pNewView->m_hWnd, GWL_ID));
        ::SetWindowLong(pNewView->m_hWnd, GWL_ID, temp);
    
        // Display and update the new current view - hide the old one    
        pActiveView->ShowWindow(SW_HIDE);
        pNewView->ShowWindow(SW_SHOW);
        ((CFrameWnd*) m_pMainWnd)->SetActiveView(pNewView);
        ((CFrameWnd*) m_pMainWnd)->RecalcLayout();
        pNewView->Invalidate();
        return pActiveView;
    }
    

    Nun könnt Ihr mit

    SwitchView( 0 );  // bzw
    SwitchView( 1 );
    

    herum switchen

    [ Dieser Beitrag wurde am 20.06.2003 um 10:04 Uhr von goochie editiert. ]

    [ Dieser Beitrag wurde am 20.06.2003 um 10:19 Uhr von goochie editiert. ]



  • @goochie
    WOW!!! Danke, das werd ich gleich heute Abend mal austesten...

    @RenéG
    Dir ist das sicher alles superklar...
    Ist nicht böse gemeint, aber es sind nicht alle so super fit in der MFC wie Du und alle haben mal klein angefangen. Wir wollen nur dazulernen - deshalb sind wir doch hier, oder?

    Gruß
    Chris



  • Hallo

    Nene auf keinen Fall Undank eher ganz das Gegenteil.
    Ich hab auch probiert den Code anzupassen. (Variablen raus, Klassennamen ändern,...)

    Jetzt funktioniert das soweit, dass er im SDI in irgend eine, nicht von mir erstellte Funktion (SetTitle) springt und der Debugger da meckert. Ok ist auch irgnedwie klar.
    Im MDI passiert gar nichts - kein Fehler, aber auch keine Änderung.

    Hab jetzt nochmal die MSDN SetActiveView(...) gefunden. Was ist mit der, geht die nicht. Ich kriegs leider icht ohne Fehler hin.

    THX 🙂



  • @goochie

    Danke werd das heute Nachmittag mal ausprobieren.
    Natürlich mit Anpassung an meinen Code... 😉 😃 😉

    Danke 🙂



  • @goochie
    Juhuu es funktioniert 🙂

    Danke an Alle



  • Ok, das mit dem Wechseln der Views funktioniert jetzt ganz gut.

    Mein Programm verwendet ein SplitterWindow (wird in InitInstance geteilt). Links ist ein CTreeView und rechts ein CFormView.
    Wnn ich nu, je nachdem was im CTreeView passiert, die entsprechende CFormView laden will, ersetzt er die komplette alte Ansicht, also auch das CTreeView. Wie kann man das ändern ?

    THX 🙂


Anmelden zum Antworten