Nichtmodaler Dialog soll Funktion aufrufen



  • Wie kann man von einem nichtmodalen Dialog, eine Funktion des übergeordneten
    Fensters aufrufen ? Folgender Code:
    Meine CDialog-Klasse heisst CMeinDialog, und das Dialog-Fenster wird aufgerufen in CMeinView.

    ...CMeinView::OnRButton ...
    CMeinDialog* dlg = new CMeinDialog();
    dlg->Create(IDD_DIALOG1, this);
    dlg->ShowWindow(SW_SHOW);

    Über den this-Zeiger müsste der Aufruf gelingen !
    In der Headerdatei von CMeinDialog:
    #include "MeinView.h"
    CMeinView* vi;

    Im Konstruktor von CMeinDialog:
    CMeinDialog(..., pParent)
    {
    vi = pParent;
    }

    In CDialog der Button-Händler:
    vi->AufrufDerFunktionInCMeinView();

    Das Programm lässt sich nicht compilieren ? Weiss jemand Rat ?



  • Ich nochmals: Im Buch: Inside Visual C++ .NET von Shepherd und Kruglinski, Seite 150, steht eine komplizierte Lösung des Problems, allerdings sehr sehr umständlich.
    Bei C# geht das problemlos und einfach !
    Nur bin ich auf C++ mit den MFC, angewiesen, weil ich ein grosses Programm,
    weiterentwickle und warte.
    Gegoogelt habe ich auch schon.



  • MeinView.cpp

    CMeinDialog* dlg = new CMeinDialog(this);
    

    Dann musst du natürlich einen Konstruktor für deine "CMeinDialog"-Klasse anpassen, dass der einen Zeiger vom Typ "CMeinView" erwartet. Und deine CMeinView-Klasse braucht einen Datenmember vom Typ "CMeinView*".

    MeinDialog.h

    class CMeinView;  // forward declaration ... so kann man sich hier den include
                      // der MeinView.h sparen.
    
    class CMeinDialog
    {
    // ...
    CMeinView* vi; 
    // ...
    };
    

    MeinDialog.cpp

    CMeinDialog::CMeinDialog(CMeinView* myView) : vi(myView)
    {
    }
    
    CMeinDialog::OnButtonClicked(...)
    {
      // ...
      vi->HierIstDieFunktionDeinerCMeinViewKlasseAufrufbar();
      // ...
    }
    

    Danach hat dein Dialog immer einen Pointer von deinem Hauptfenster und du kannst in jeder deiner Dialog-Methoden mit diesem "vi" Pointer auf die Methoden deines Hauptfensters zugreifen.
    So ist es zwar möglich, aber wahrscheinlich nicht gerade der sauberste Weg.

    Eine alternative wäre unter Umständen ja auch noch, die Methode deiner CMeinView-Klasse statisch zu machen (d.h. wenn du dort auf keine anderen Klassen Member zugreifen solltest). Dann könntest du diese statische Methode auch ganz einfach in deiner Dialog-Klasse aufrufen. (was schon mal sauberer wäre, als die Zeiger-Variante von oben ... meines Erachtens).

    Aber am besten dürfte halt sein, wenn du diese Funktion irgendwo anders hinpacken könntest, wo beide deiner Klassen drauf zugreifen könnten.



  • P.S.:
    In der Datei für den Dialog musst du natürlich dann noch den Header deiner Hautviewklasse includieren.

    MeinDialg.cpp

    #include "MeinView.h"
    
    //...
    


  • Die sauberste Methode ist dem Dialog Das Handle auf den View mit zu geben und über SendMessage eine Funktion in View aufzurufen. Alles andere ist in meinen Augen frikelei und da die MFC nicht Threadsafe ist auch nicht sicher.



  • Im obigen Buch, wurde erwähnt, anstelle des nichmodalen Dialogs, CFormView zu
    verwenden. Aber wie ?


  • Mod

    MFC-Arbeiter schrieb:

    Im obigen Buch, wurde erwähnt, anstelle des nichmodalen Dialogs, CFormView zu
    verwenden. Aber wie ?

    Sag doch erstmal was DU willst. Hast Du denn ein Dokument. Hast Dui überhaupt eine Doc/View Struktur?
    Wenn nein: Für ein CFormView brauchst Du Frame, Document, und View...

    Das Buch mag Recht haben wenn es sich um eine komplette Anwednung handelt. Aber wenn es um so etwas wie ein Suchfenster geht, dass immer da sein sol, oder ein Fenster für Properties oder so, müsstest Du evtrl. auch an ein dockable Window denken.

    Also sag uns was Du willst und stelle Deine Frage bitte präziser!



  • Martin, Du hast wohl recht. Um einen nichtmodalen Dialog zu erstellen, muss man
    wohl die Lösung mit SendMessage verwenden. Ich dachte, einen nichtmodalen Dialog einfacher mit CFormView bauen zu können, aber das geht wohl nicht.


  • Mod

    Man muss kein SendMessage verwenden. Du kannst ja an den Dialog jeden beliebigen Zeiger einer anderen Klasse mitgeben.



  • Martin,
    Um eine Funktion von CMeinView in MeinDialog.cpp aufzurufen braucht es folgendes:

    CMeinView* vi;
    vi->FunktionVonMeinView();

    Dazu muss CMeinView in MeinDialog eingebunden werden:
    Es wird also CDialog in MeinView, und CMeinView in MeinDialog eingebunden.
    Ich habe es nochmals versucht:
    Habe ein neues Projekte angelegt, mit einem Dialogfeld und einer CDialog-Klasse
    versehen, und die Verweise wie oben eingerichtet. Ausserdem kein Code hinzu-
    gefügt. Es kam wieder der Compilerfehler:
    "Es fehlt ';' vor ''"
    bei: CMeinDoc
    GetDocument() const;
    Keine Ahnung wie das zu verstehen ist !

    Wenn man dem Konstruktor von CMeinDialog "this" übergibt, so denke ich geht
    folgendes nicht:
    CMeinView* vi;
    CView* vi2; // Wenn man CMeinView nicht einbinden kann.
    vi2 = vi;
    vi2->FunktionVonMeinView(); // Weil in CView es keine Funktion:
    FunktionVonMeinView gibt !

    Wahrscheinlich hat das Buch, wo die Lösung mit SendMessage beschrieben ist,
    doch recht, sonst ginge das sehr einfach !
    Was meinst Du Martin ?



  • Das Grundprinzip von MFC-Zeiger hast Du ausprobiert?


  • Mod

    Ich weiß immer noch nicht was Du eigentlich vorhast, aber ich kann Dir sagen:

    Einen View in einen Dialog einbinden geht nicht. So scheinen mir Deine Versuche.

    Wenn Du einen simplen nicht modalen Dialog der einen Zeiger auf den View mitbekommt, dann kannst Du einfach über den Zeiger des Views die Funktion aufrufen. Wo ist das Problem?



  • Den Zeiger übergibt man dem Dialog Konstruktor:
    In der Prozedur-Schnittstelle gibt es ein Parameter namens "parent".
    Dieser enthält den Zeiger. Den muss ich um ihn später zu verwenden einer
    Variablen vom Typ CView oder CMeinView zuweisen. Und dann sollte man die
    Funktion aufrufen können. Oben habe ich beschrieben, dass man CMeinView
    nicht einbinden kann, oder es ist mir nicht gelungen. Wie soll ich die Funktion
    aufrufen können ? vi->Funktion(); Aber woher bekomme ich vi ? CView nicht und
    CMeinView nicht ...


  • Mod

    Bau einen eigene Membervariable in dem CDialog ein. Und setze die. Dann kannst Du innerhalb des DIaloges darauf zugreifen. Wo ist das Problem?

    Das Parent würde ich nicht verwenden.
    Wenn Du Das Parent verwendest kannst Du einen Down cats machen mit GetParent

    STATIC_DOWNCAST(CMyView,GetParent())->MeineFunktion();



  • Hast Du vielleicht ein Problem mit der Vorwärtsdeklaration?

    Hier etwas Pseudocode:

    In MyDialog.h
    Vor der Klassendeklaration von CMyDialog: Class CMyView; //Vorwärtsdeklaration
    Dann als Member der Dialogklasse z.B. CMyView *m_pMyView;

    In MyView.cpp

    CMyDialog dlg;
    dlg.m_pMyView = this;
    dlg.DoModal();
    

    In Dialog.cpp

    #include "myView.h"
    //...
    m_pMyView->Func(); nutzen
    


  • Martin, welchen Typ soll die Membervariable haben, und worauf soll ich sie
    setzen ?



  • Vorwärtsdeklarationen habe ich schon eingesetzt. Kann mir jemand erklären,
    was es sich mit der Fehlermeldung, ( wie oben beschrieben ) auf sich hat ?


  • Mod

    Meine Güte.
    Lerne mal etwas Basics.

    Natürlich auf den Klassentyp, dessen Funktion Du ausführen willst.

    Ehrliche Frage: Hast Du irgendeinen Plan den Du verfolgst?



  • So nun aber zum Schluss:
    STATIC_DOWNCAST geht nicht weil der Bezeichner CMyView nicht sichtbar ist.
    Wollte ich ihn einbinden: #include "MyView.h" mit oder ohne Vorwärtsdeklaration,
    kommt die Fehlermeldung " ... ';' vor '*' ... " wie oben beschrieben.
    Probier es halt mal selber aus:

    1. Ein neues Projekt anlegen.
    2. Eine Dialogfeldvorlage, und eine CDialog-Klasse anlegen.
    3. Beidseitiges include, mit oder ohne Vorwärtsdeklaration.
    4. Compilieren.
      Eine Sache von zwei Minuten.
      Ansonsten würde ich sagen, lassen wir das Thema ruhen.
      Ich verfolge keine bösartige Absicht.
      Trotzdem Danke für die Mühe !


  • Ersetze bitte CMyView durch CMeinView, wie ich es oben gehandhabt habe. Wollte ich
    eine Variable vom Typ CMeinView anlegen, um die Funktion aufzurufen, muss ich erst mal MeinView.h includieren. Das geht nicht !!! Basics ! Was solls ...


Log in to reply