MFC View Architektur



  • Hallo!

    Ich beschäftige mich erst seit kurzem mit den Dokument/Ansicht Architektur (DAA) der MFC. MFC Kenntnisse habe ich allerdings schon. Habe allerdings alles bisher mit Dialogen gelöst.

    Nun wollte ich mich einmal an die DAA setzen - habe bereits ein wenig im Buch Inside VC++ 6 gestöbert - bin allerdings etwas iritiert. Warum läuft zusätzlich alles über diese Dokumente?

    Folgendes Problem:
    In meinem konkreten Fall brauche ich keine Dokumente. Wenn ich mit dem Assistenten (VS 2008) eine neue SDI Applikation erstelle OHNE DAA kann ich nicht ohne weiteres Klassen - abgeleitet von CView - inkl. Splitter benutzen. Wenn ich den Code von Hand einfüge und die Klasse CChildView lösche, in OnCreateClient regulär meinen Splitter mit den zwei Views erstelle, wird die OnInitialUpdate Methode des zu erst erstellten Views 2x aufgerufen. Hmm, habe ich einmal ein vom Assistenten erzeugtes DAA Programm gedebuggt und gesehen, dass wenn pContext->m_pNewViewClass nicht leer ist, OnInitialUpdate nur einmal aufgerufen wird. Hmm, allerdings wird das Hauptrahmenfenster CMainFrame in der Applikationsklasse auch ganz anders erzeugt.
    Ich habe ein wenig herumprobiert und heraus kam folgender Code:

    // Applikationsklasse InitInstance
        CMainFrame* pFrame = new CMainFrame;
    	if (!pFrame)
    		return FALSE;
    	m_pMainWnd = pFrame;
    
        CCreateContext CreateContext;
    
        CreateContext.m_pCurrentFrame = pFrame;
        CreateContext.m_pNewViewClass = RUNTIME_CLASS(MyCustomView_1);
    
    	// create and load the frame with its resources
    	if (!pFrame->LoadFrame(IDR_MAINFRAME,
    		WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
    		&CreateContext))
            return false;
    
        pFrame->InitialUpdateFrame(0, TRUE);
    
       // The one and only window has been initialized, so show and update it
    	pFrame->ShowWindow(SW_SHOW);
    	pFrame->UpdateWindow();
    
    // CMainFrame
    BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpCreateStruct, CCreateContext *pContext)
    {
        this->m_Splitter.CreateStatic(this, 2, 1);
    
        CRect Rect;
    
        GetClientRect(&Rect);
    
        this->m_Splitter.CreateView(0, 0, RUNTIME_CLASS(MyCustomView_1), CSize(10, Rect.Height() / 2), pContext);
        this->m_Splitter.CreateView(1, 0, RUNTIME_CLASS(MyCustomView_2), CSize(10, Rect.Height() / 2), pContext);
    
        return TRUE;
    }
    

    Meine Frage nun: Ist das korrektes "MFC-C++" in der InitInstance also folgende Zeilen:

    // Hier: m_pNewDocTemplate etc. werden nicht gesetzt
    CCreateContext CreateContext;
    
        CreateContext.m_pCurrentFrame = pFrame;
        CreateContext.m_pNewViewClass = RUNTIME_CLASS(MyCustomView_1);
    
    // Hier: Erster Parameter *pDoc ist 0
    pFrame->InitialUpdateFrame(0, TRUE);
    

    Kann man das so machen oder ist das grober Unfug und funktioniert nur zufällig?

    P.S.: Ich hoffe ich konnte halbwegs mein Problem schildern

    Gruß Jochen



  • die idee hinter dem "Document" ist halt das "MVC-Modell" - das ist halt trennung von der view und den daten



  • Mr Evil schrieb:

    die idee hinter dem "Document" ist halt das "MVC-Modell" - das ist halt trennung von der view und den daten

    Ja, ich habe gerade noch mehrmals nachgelesen. Also Trennung von Ansicht (CView) und Daten (CDocument).

    In bräuchte allerdings nur 2x CView und einen Splitter. Das scheint allerdings nicht "gewollt" zu sein, oder?

    Gruß Jochen



  • man kann natuerlich die klassen so aufbauen das du nur die beiden views hast
    einfach eine SDI anwendung erstellen (ohne DocView)
    in der main cpp dann das erstellen der CView klasse weg lassen und in dem mainframe dann ein splitter platzieren mit den beiden klassen - dann kannst du sehen wie du untereinander {mainframe als controler} kommunizierst - ueberhaupt kein problem
    hab schon selber ein paar anwendungen so aufgesetzt wo ich main cpp - frame wnd - linke klasse, rechte klasse als basis genommen habe



  • Mr Evil schrieb:

    man kann natuerlich die klassen so aufbauen das du nur die beiden views hast
    einfach eine SDI anwendung erstellen (ohne DocView)
    in der main cpp dann das erstellen der CView klasse weg lassen und in dem mainframe dann ein splitter platzieren mit den beiden klassen - dann kannst du sehen wie du untereinander {mainframe als controler} kommunizierst - ueberhaupt kein problem
    hab schon selber ein paar anwendungen so aufgesetzt wo ich main cpp - frame wnd - linke klasse, rechte klasse als basis genommen habe

    Dann erhalte ich allerdings oben beschrienes Problem. Also der zweimalige Aufruf von OnInitialUpdate des zu erst erstellten Views.



  • achso, naechste mal muss ich genauer lesen

    das es mehrfach aufgerufen wird ist normal - die funktion wird immer aufgerufen wenn diese klasse den focus erhaelt - wenn du n anderes fenster aktivierst und zurueck switchst, wird es wieder aufgerufen

    umgeh das ganz einfach

    class
    bool init = true

    if(init)
    {
    init = false
    }



  • Mr Evil schrieb:

    achso, naechste mal muss ich genauer lesen

    das es mehrfach aufgerufen wird ist normal - die funktion wird immer aufgerufen wenn diese klasse den focus erhaelt - wenn du n anderes fenster aktivierst und zurueck switchst, wird es wieder aufgerufen

    umgeh das ganz einfach

    class
    bool init = true

    if(init)
    {
    init = false
    }

    Eine Membervariable die die Initialisierung überprüft kam mir auch schon in den Sinn. Allerdings fand ich das nicht so gut, denn im Normalfall wird OnInitialUpdate nur einmale aufgerufen. Also ist da irgendwo der Wurm drin.

    Ich habe es jetzt in etwa so gelöst wie hier:
    http://simplesamples.info/MFC/WithoutTemplates.php

    P.S.: Werden eigentlich irgendwelche Registrierungseinträge o.ä. gemacht wenn ich ein Dummy-Dokument nutze?

    Gruß Jochen



  • ::Jochen schrieb:

    denn im Normalfall wird OnInitialUpdate nur einmale aufgerufen

    in deinem fall falsch

    MSDN schrieb:

    The default implementation of this function calls the OnUpdate member function with no hint information
    ...
    If your application supports variable-sized documents, use OnUpdate to update the scrolling limits every time the document changes.

    Durch den splitter hast du genau das

    http://msdn2.microsoft.com/en-us/library/xc7fw3a0(VS.80).aspx


Log in to reply