[C++] Zugriff auf Dialog aus anderem Dialog

JoachimJogi

Mitglied
Hi,

ich kann mir nicht vorstellen, dass mein Problem ein "spezielles" ist, eher ein ganz alltägliches und ich suche nur in die falsche Richtung. Daher wäre ich dankbar, wenn mir jm. auf die Sprünge helfen könnte und sagen wie die "richtige" Lösungsvariante ist.

Das Testprogramm soll so aussehen
http://jogipalace.jo.funpic.de/mfc/demo.jpg

Zur besseren CodeÜbersichtlichkeit, ist der "dünne Rahmen" ein eigener Dialog. Das muss ich so machen, weil hier später ein CTabCtrl hinkommt, indem auch jedes Tab ein eigener Dialog ist.
Ich möchte durch das Betätigen des Button1 einen Text in der Editbox ausgeben. Das Problem ist, dass die Editbox von einem anderen Dialog stammt.

Wie mache ich das?

=======================

Meine bisherige Lösungsvariante ist:

CMyTestDlg* p; // Das hier ist der "innere" Dialog
p = (CMyTestDlg*) AfxGetApp()->m_pMainWnd;
p->testMethode(); // Diese Methode des "äußeren Dialoges" schreibt einen Text

Diese Methode ist sehr unschön, da dieser 3Zeiler in jeder Funktion, in der ich etwas ausführen will reingeschrieben werden muss.

Ich vermute stark,d ass an meinem Gesamtkonzept etwas nicht stimmt. Daher die allgemeine Frage: Wie realisiert man einen Dialog auf dem zb ein CTabCtrl und andere Elemente zu sehen sind? Irgendwie müssen die Tab Seiten auch Zugriff auf den Rest haben

VIELEN DANK!
 
Ich kann meine Frage auch umformulieren:

Nehmen wir, ich habe einen (Haupt)Dialog mit einem TabCTrl. Hierbei kann man zwischen verschiedenen Tabs, also zwischen verschiedenen Dialogen umschalten. (TabDlg1,TabDlg2, ...)

auf TabDlg5 möchte ich ein Log integrieren. Wenn man zb auf TabDlg1 einen Button drückt, soll im Editfeld auf TabDlg5 ein Eintrag erscheinen.

Wie mache ich das? Ich hab inzwischen eine ganze Reihe an Foren (auch englische) durchgearbeitet und stoße immer wieder auf den umgekehrten Fall (Wie spreche ich eine EditBox in einem TabDialog aus dem Hauptdialog an). In meinem FAll möchte ich aber aus einem Tab Dialog einen anderen Tab Dialog ansprechen (bzw ähnlicher Fall: aus einem Tab Dialog den Hauptdialog).


P.S.: Bitte jetzt nicht den Hinweis, dass Logging in Dateien gehört. Hierbei handelt es sich um ein konstruirtes Beispiel.

Vielen Dank!!
 
Ich weiss nicht, warum so viele Leute ein Problem mit sowas haben, nur weil es nicht in ein OOP-Design-Pattern passt.

Du brauchst einen Pointer auf den anderen CDialog. Irgendwo erstellst du den ja. Jetzt pappst du den Pointer irgendwo hin, wo du vom anderen CDialog aus Zugriff drauf hast.

Das kann jetzt global rumliegen (nicht so schön) oder in die CWinApp als Member aufgenommen werden.

Du kannst auch den Constructor von dem einen CDialog um einen Parameter erweitern, der einen Pointer auf den anderen CDialog übernimmt. Da musst du dann nur bei der Erstellreihenfolge aufpassen.

Auf kurz: Du brauchst etwas, dann pack es irgendwo hin, wo du drauf zugreifen kannst.
 
Im Spezialfall TabCtrl kannst du dir den Pointer zum Dialog über die Methode "GetItem()" von CTabCtrl holen:
C++:
// Im Click-Eventhandler von TabDlg1 ausführen

TCITEM item;
item.mask = TCIF_PARAM;
((CTabCtrl *)GetParent())->GetItem(4 /*die 5. Tabkarte*/, &item);
    
CTabDlg5 *pDlg = (CBTabDlg5 *)item.lParam;
    
if( pDlg && ::IsWindow(pDlg->GetSafeHwnd()) )
{
    // irgendwas tun
}
Gruß
MCoder
 
@Endurion: Leider kommt es mir überhaupt nicht so vor, als ob dieses Problem viele Leute haben. Ich habe wircklich schon viele Tutorials und Foren gelesen, stoße aber nicht auf dieses Themengebiet.

Dein Satz "Auf kurz: Du brauchst etwas, dann pack es irgendwo hin, wo du drauf zugreifen kannst." trifft es genau richtig! Danke! (Manchmal braucht man einfach eine Bestätigung, dass es ganz einfach ist)


@MCoder: Dir natürlich auch vielen Dank für den "Tipp" mit GetItem.

Es klappt noch nicht ganz mit dem bekannt machen, wahrscheinlich include fehler, aber das probier ich erstmal selber.


Danke!
 
Zuletzt bearbeitet:
Es klappt leider immer noch nicht wie ich will ;(

Wieder ein konstruiertes Beispiel, diesmal mit
CTryApp, CTryDlg und InnerDlg.
Ich möchte von InnerDlg Zugriff auf CTryDlg bekommen.

1) InnerDlg anzeigen, indem Membervariable InnerDlg in CTryDlg initialisiert und angezeigt wird (keine Probleme)

2) Member Variable vom Typ CDialog* in InnerDlg erzeugen. Name: m_super;

3) Dem Konstruktor von InnerDialog gebe ich einen this Zeiger mit (aufgerufen vom CTryDlg::OnInitDialog() )

4) Im Konstruktor speichere ich die übergebene Adresse.

In der InnerDlg.cpp ist die TryDlg.h includiert. Wenn ich jetzt mit
((CTryDlg*)m_super)->MessageBox("hallo","",0); einen Test mache, funktioniert es.
Aber bei
((CTryDlg*)m_super)->setLog("hallo welt"); kommt ein Speicherfehler.

Meine setLog Methode ist richtig.
Code:
void CTRYDlg::setLog(CString c)
{
   m_strEdit.Format("ASdf");
   UpdateData(false);
}
, da sie lokal aufgerufen funktioniert.


Ist es überhaupt richtig, dass ich eine Membervariable vom Typ CDialg* anlege? Wenn ich nämlich direkt versuche CTryDlg* anzulegen, meckert er, dass er den Bezeichner nicht kennt. Nach dem includieren von TryDlg.h in der InnerDlg.h geht dann nix mehr, da er keine der beiden Dateien compiliert. (Beides mal "; erwartet", also wie bei unbekannten Datentypen.

Ich könnt mri auch nicht vorstellen, wie der Compiler dass dann auflösen soll, denn um TryDlg.h zu kompilieren benötigt er die InnerDlg.h und anders herum ebenso.

Lege ich die Membervariablen falsch an?
 
Aber bei
((CTryDlg*)m_super)->setLog("hallo welt"); kommt ein Speicherfehler.
Vom Prinzip ist eigentlich alles richtig. Kannst du mal die genaue Fehlermeldung zeigen? Hast du "setLog" auch als "public" deklariert?
Ist es überhaupt richtig, dass ich eine Membervariable vom Typ CDialg* anlege? Wenn ich nämlich direkt versuche CTryDlg* anzulegen, meckert er, dass er den Bezeichner nicht kennt.
Kann man schon so machen, aber gleich den Typ "CTryDlg*" anzulegen ist natürlich günstiger, weil du dir später das Type-Casting ersparst. Das Problem mit dem unbekannten Speichertyp kannst du lösen, indem du in "InnerDlg.h" vor der Klassendeklaration eine sogenannte Vorwärtsdeklaration einfügst:
C++:
class CTryDlg;    // Vorwärtsdeklaration

class CInnerDlg : public CDialog
{
    // ...
};
TryDlg.h kannst du dann in der .cpp belassen. Vorwärtsdeklarationen funktionieren nur bei Zeigern.

Gruß
MCoder
 
Hallo McCoder.

vielen Dank für deine Antwort!

Es funktioniert alles, wie ich es will. Durch die Vorwärtsdeklaration kann ich alles so formulieren, wie es mir logisch erscheint. Der Speicherfehler ist weg. Ich hatte es public. Den Fehler möchte ich aber auch gar nicht reproduzieren, wahrscheinlich eine Kleinigkeit.

Somit wäre dieses Topic erledigt!

Grüße an alle Forumuser!
 

Neue Beiträge

Zurück