Hallo, ich habe eine Frage zu Nachrichten zwischen Dialogen in MFC-Anwendungen (MS VC++ 6). Wenn ich von einem Dialog aus einen Handler in einem anderen Dialog oder dem Hauptfenster aufrufen möchte (oder Daten übergeben), mache ich bisher folgendes: In der Klasse CMainFrame (MainFrm.cpp) implementiere ich für jede Nachricht einen Messagehandler, beispielsweise so: ON_MESSAGE(WM_CLOSEPROJDLG, OnForwardMsg_ProjDlgCl) In CMainFrame schreibe ich dann eine Umleitung, Beispiel: void CMainFrame::OnForwardMsg_ProjDlgCl(){ {Der_Empfaenger}.SendMessage(WM_CLOSEPROJDLG); CWnd *pwnd = GetWindow(GW_CHILD); pwnd -> SendMessage(WM_CLOSEPROJDLG); } In diesem Beispiel ist {Der_Empfaenger} meine Zielklasse. Die Umleitung spreche ich aus dem Dialog an, beispielsweise so: CWnd* pwnd = GetWindow(GW_OWNER); pwnd -> SendMessage(WM_CLOSEPROJDLG); Dieses Hin- und hergerufe kommt mir sehr umständlich vor, so dass ich denke dass ich ungeschickterweise Konzepte aus anderen Sprachen schlecht in VC++ 6 übertragen habe. Meine Frage: Gibt es eine bessere/elegantere Methode? Gruß & danke, Nils
Du musst dich der Grundsatzfrage stellen: Will ich über Messages gehen bzw. was verspreche ich mir von den Messages? Wenn dir dafür kein wirklich vernünftiger Grund einfällt, dann musst du nicht über Messages laufen, sondern kannst das alles auch mit normalen Funktionsaufrufen machen. Der Mainframe muss ja auch so alle Dialoge kennen (sind offenbar nicht modale Dialoge) um die Message weiterrouten zu können. Ob der Mainframe dem jetzt eine Message schickt, oder ob der Dialog eine ganz spezielle Funktion dafür zur Verfügung stellt, ist gehupft wie gesprungen. Auf der anderen Seite ist es in einem MFC Programm von überall leicht , an den Mainframe rannzukommen, so dass ein direkter Aufruf der Verteilfunktion in CMainFrame nichts im Wege steht. Wenn es dir aber tatsächlich wichtig ist, die einzelnen Klassen vollständig voneinander zu entkoppeln, dann ist dein Message-Ansatz schon ok.
Hallo Karl Heinz, danke für die ausführliche Antwort. > ... (sind offenbar nicht modale Dialoge) ... Doch, auch für modale Dialoge wähle ich diesen Weg. Ergeben sich da aus Deiner Sicht Schwierigkeiten? > Wenn es dir aber tatsächlich wichtig ist, die einzelnen Klassen > vollständig voneinander zu entkoppeln, dann ist dein Message-Ansatz > schon ok. Ja, das versuche ich tatsächlich durchzuhalten. Aber wie ist das mit den Dialoginstanzen, die Mainframe bekannt sind? Wie kann ich Dialoginstanzen dieses Wissen bekannt geben, wenn ich eine bestimmte Methode in einem bestimmten Dialog ansprechen möchte? Sollte ich dann die entsprechende Dialoginstanz globalisieren und das den miteinander kommunizierenden Dialogen per 'extern' bekannt geben? Das erschien mir ein bisschen windig - ich denke ich habe hier irgendwie Scheuklappen vor den Augen und sehe die simple Lösung nicht. Danke schon mal für die Info, dass mein bisheriger Lösungsansatz adäquat ist - das beruhigt mich etwas. Gruß, Nils
Warum müssen Dialoge miteinander kommunizieren? Mit dem "model-view-controller"- oder "Document-View"-Konzept hat das nicht viel zu tun.
Hallo Rufus,
> Warum müssen Dialoge miteinander kommunizieren?
Mal ein konkretes Beispiel:
In einem modalen Dialog habe ich eine Eingabemaske. Beim Schließen des
Dialogs soll der Wert in der Eingabemaske einen Handler im Hauptfenster
aufrufen, beispielsweise, um eine ComboBox um diesen Wert zu erweitern.
Wie kann man das ohne Nachrichten lösen?
Der Dialog ist modal, also gibt es eine Stelle, an der er aufgerufen wurde. Das wird irgendwo in einem Ereignishandler eines Views oder eines Frame Window geschehen. An eben dieser Stelle kann der Rückgabewert von CDialog::DoModal() untersucht werden. Z.B. bei IDOK werden dann die im Dialog manipulierten Dinge ausgewertet und dann kann der View oder wer auch immer etwas damit anfangen.
Rufus t. Firefly schrieb: > An eben dieser Stelle kann der Rückgabewert von CDialog::DoModal() > untersucht werden. Z.B. bei IDOK werden dann die im Dialog manipulierten > Dinge ausgewertet und dann kann der View oder wer auch immer etwas damit > anfangen. Oder um das einmal etwas allgemeiner zu formulieren. Ein modaler Dialog ist selten in der Verlegenheit, dass andere Programmteile sofort von seinen Änderungen in Kentnis gesetzt werden müssen (Ausnahme: Man baut einen Apply-Button ein. Daher sieht man den auch eher selten :-) Die übliche Vorgehensweise ist: Der Dialog geht davon aus, dass seine Vorgabe-Werte beim Betreten der OnInitDialog richtig eingestellt wurden. Zuständig dafür ist derjenige, der den Dialog erzeugt und das DoModal() aufgerufen hat. Seine Aufgabe ist es, den Dialog mit den Ausgangwerten zu versorgen. Dann macht der Dialog sein Ding Prüft im OnOK Handler meinetwegen noch, ob irgendwelche Randbedingungen erfüllt sind und beendet sich Dann kommt wieder der Aufrufer des Dialogs zum Zug. Seine Aufgabe ist es jetzt, im OK-Fall sich vom Dialog die Werte abzuholen und weiter zu verteilen / weiter zu verarbeiten. Was ein Dialog nicht tun sollte: Direkt auf der Datenstruktur des Dokuments arbeiten. Das macht die Behandlung des Cancel Buttons schwierig. Auch ist es dann oft sehr schwer sicherzustellen, dass die vom Benutzer veränderten Daten in sich konsistent sind, wenn im Dialog bei jeder Änderung gleich die Dokument-Datenstruktur verändert wird. Was ein Dialog auch nicht tun sollte: Sich die Daten selbst zusammensuchen. Es ist der Programmteil, der den Dialog öffnet, der dafür zuständig ist. Aus Sicht des Dialogs sollte die Sache so sein: * Ich kriege Daten vorgesetzt. Und zwar in Form von Kopien. Verändere ich die Daten, dann passiert erst mal nichts. * der Benutzer bearbeitet sie * ich hinterlasse die Daten so, dass mein Vorgesetzter sie sich abholen kann. Jetzt ist es gut, dass ich immer nur auf Kopien gearbeitet habe, denn meinem Aufrufer steht es damit frei die Änderungen ganz einfach zu ignorieren (zb weil ich ihm mitteile dass mein Benutzer auf Cancel gedrückt hat) Mit einem derartigen Vorgehen (und einer zentralen UpdateControls Funktion im Dialog, in der Dialogelemente inaktiv/aktiv gesetzt werden) waren zumindest bei mir die meisten Dialoge bessere Fingerübungen ohne gröbere Komplikationen. Bei nicht-modalen Dialogen ist die Situation häufig unangenehmer. Aber die sind ja nicht betroffen.
Hallo Rufus, hallo Karl Heinz, > An eben dieser Stelle kann der Rückgabewert von CDialog::DoModal()... Das war das Wissen, das mir fehlte. (Hatte ich mir zwar schon angesehen, hatte aber offenbar Tomaten auf den Augen). > Was ein Dialog nicht tun sollte: Direkt auf der Datenstruktur des > Dokuments arbeiten. Ja, und genau das hatte ich vor und es kam mir selber nicht ganz koscher vor. Vielen dank für Eure ausführlichen Erklärungen - hat mir sehr weitergeholfen. Gruß, Nils
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.