Nachricht an alle Dialoge
-
Hallo,
kurz vorneweg, ich habe wenig Ahnung von dem was ich da tue
Aber da müssen wir jetzt durch.Ich habe in meiner MFC-Anwendung einen CDialog. Von diesem Hauptdialog aus werden weitere Unterdialoge gestartet die gemeinsam zur gleichen Klasse gehören.
In etwa so hier:CWnd dummy; // damit dialog nicht immer im vordergrund CDialog *newdialog; int dialogid = IDD_VIEW_DATA; newdialog = new CViewData(); newdialog->Create(dialogid,&dummy); newdialog->ShowWindow(SW_SHOWNORMAL);Die Anzahl der Unterdialoge kann jederzeit variieren. Mal sind mehrere gleichzeitig geöffnet mal gar keines.
So weit Funktioniert das Prima. Nun suche ich einen eleganten Weg ALLEN geöffneten Unterdialogen mitzuteilen, dass Sie etwas tun sollen. Z.B. Daten in einem Feld aktualisieren.
Ich dachte da an SendMessage oder PostMessage, aber wie bekomme ich das hin, das diese Message an alle Unterdialoge gleichzeitig geht?Mit
newdialog->PostMessage(WM_NACHRICHT,0,0);tut sich nur im zuletzt geöffneten Dialog was.
Oder gibt's es eine elegantere Möglichkeit ohne Nachrichten?
Danke und liebe Grüße
Lisa

-
Du könntest die Dialoge (oder Zeiger darauf) in irgendeiner Liste (Array, STL-Container) ablegen und so immer in Schleifen einen Befehl für alle ausführen.
-
du könntest wie matze schon vorgeschlagen hat ein Bereich bilden in dem du jedes Handle eines geöffneten childdialoges ablegst.
wenn du dann die geöffneten dialoge benachrichtigen willst, durchläufst du diesen bereich und sendest via SendMessage die gewünschte nachricht.in etwa so.
HWND m_hWndDialolge[1024]={0}; int iAnzahlDlgs = 10; int wDeinLowWert,wDeinHighWert,lDeinLowWert,lDeinHighWert; for(int = 0; i <= iAnzahlDlgs; i++) SendMessage(m_hWndDialolge,WM_NACHRICHT,MAKEWPARAM(wDeinLowWert,wDeinHighWert),MAKELPARAM(lDeinLowWert,lDeinHighWert));im jeweiligen dialog ruft du das ganze dann wieder in der Nachrichtenschleife ab
switch(Message) { case WM_NACHRICHT: { wDeinLowWert = (int)LOWORD(wParam); wDeinHighWert = (int)HIWORD(wParam); lDeinLowWert = (int)LOWORD(lParam); lDeinHighWert = (int)HIWORD(lParam); } break; }
-
Hui das geht ja fix hier
Danke euch beiden.
So müsste ich mir ja auch noch merken welche Dialoge denn überhaupt noch offen sind.
Wie könnte ich denn mitbekommen, dass ein Dialog wieder geschlossen wird?Wenn ein anderer nebengeordneter Dialog auch eine Nachricht an meine VIEW_DATA Dialoge senden will, muss ich dann mein HWND-Array global vorhalten?
liebe Grüße
Lisa
-
Lisa2ab schrieb:
So müsste ich mir ja auch noch merken welche Dialoge denn überhaupt noch offen sind.
du zwar nicht, aber dein programm auf jeden fall

Lisa2ab schrieb:
Wie könnte ich denn mitbekommen, dass ein Dialog wieder geschlossen wird?
in dem dein ChildDialog (der geschloßen wird) eine nachricht an den Hauptdialog senden das sich was geändert hat, und diesen auffordert den HWND bereich neu zu überarbeiten.
mit IsWindow(HWND); kannst du prüfen welcher Dialog noch existiert...Lisa2ab schrieb:
Wenn ein anderer nebengeordneter Dialog auch eine Nachricht an meine VIEW_DATA Dialoge senden will, muss ich dann mein HWND-Array global vorhalten?
nicht zwingend... wenn dein nebengeordneter Dialog eine Nachricht an den Hauptdialog senden und dein Hauptdialog wiederum die nachricht an seine Childs verteilt dann nicht.
-
Gibt es nicht doch noch eine schickere Methode? Ich dachte man könnte so eine Art Broadcast an alle Fenster der eigenen App senden.
Ich bräuchte eine Lösung, allen meinen VIEW_DATA Fenstern mitzuteilen, dass z.B. neue Daten vorliegen und diese nun angezeigt/aktualisiert werden sollen.
Vielleicht, sollte ich doch besser einen globalen Counter, für den Fall, dass neue Daten vorliegen, hochzählen.
Und in meinen VIEW_DATA Dialogen mittels Timer z.B. alle 10ms nachsehen ob sich dieser Counter verändert hat und dann neu zeichnen.Wobei mir da irgendwie nicht gefällt, dass da unter Umständen mächtig viele Timer im Hintergrund unnütz Systemzeit verbraten.

-
Wurde doch schon alles gesagt oder?
Warum Nachricht?
- Bau Dir ene Dialog-Basisklasse mit einer Funktion RefreshData.
- Wenn Du einen Dialog der Basisklasse erzeugst, wird dieser sofort in eine statische Liste aufgenommen.
- Beim zerstören des Dialoges wird der Dialog aus der Liste entfernt.
- In einer statischen Funktion RefreshAll in der Dialogklasse lässt Du die Liste ablaufen und jeweils die Funktion RefreshData aufrufen.
-
Martin Richter schrieb:
Wurde doch schon alles gesagt oder?
Warum Nachricht?Weil ich irgendwie nicht mehr an die Funktionen in meinem Dialoge komme.
Wie gesagt, habe ich relativ wenig Ahnung. Ich würde es ja gerne mal für die Zukunft lernen.Beschränken wir uns erstmal auf einen Dialog. Die Liste bekomme ich dann sicher hin.
Ich habe eine Klasse
CDataView in dieser wird CDataViewDlg geöffnet.
Und aus dem CDataViewDlg möchte ich einen C3DViewDlg öffnen. Das mache ich so:CWnd dummy; // damit dialog nicht immer im vordergrund C3DViewDlg = new CViewOpenGl(); C3DViewDlg->Create(IDD_VIEW_OPENGL,&dummy); C3DViewDlg->ShowWindow(SW_SHOWNORMAL);Das klappt so weit.
Nehmen wir an, in meiner CDataViewDlg gibt es eine Funktion MyTest();
Wie komme ich von C3DViewDlg an diese Funktion ran?
Muss ich die Klasse CDataViewDlg erst nochmal in C3DViewDlg einbinden oder gibt es einen "direkten" Weg nach oben?
Und wie würde ich an eine Funktion ganz oben in der CDataView kommen?
Ich will das jetzt endlich mal grundlegend durchschauen
-
Lisa2ab schrieb:
Wie komme ich von C3DViewDlg an diese Funktion ran?
via Send- o. PostMessage.
oder du reichst nen Zeiger durch, was aber glaub ich weniger elegannt ist.
-
Übergib an den Unterdialog einfach ein Interface, oder eben den Zeiger.
Warum dnen auch hier wieder eine Nachricht?
Was soll der Satz: Du kommst nicht mehr an die Funktionen Deines Dialoges? Man kommt immer über die enstprechenden Zeiger an die Funktionen. Ob Du nun ein Handle eines Dialoges hast um eine Nachricht zu senden, oder den Zeiger auf eine Klasse ist ja wohl herzlich egal.
-
Martin Richter schrieb:
Übergib an den Unterdialog einfach ein Interface, oder eben den Zeiger.
Und hier fängt mein Verständnisproblem an. Wie genau geht das?
-
wie das mit dem Interface funzt weis ich nicht aber mit dem Zeiger auf die klasse mal aus dem bauch heraus, sollte so funzen. voraussetzung ist das eine klasse die ander kennt. also entsprechende *.h includen.
class CPrev; class CNext { public: void SetPointer(CPrev *pPrev){m_pPrev = pPrev}; private: CPrev *m_pPrev; }; class CPrev { public: CPrev() { m_Next.SetPointer(this); }; virtual ~CPrev(){}; private: CNext m_Next; };ab dem zeitpunkt der erstellung der klasse CPrev hat die klasse CNext den zeiger auf die klasse CPrev und kann auf die public funktionen und variablen zugreifen.
-
Vielen Dank
Sieht aus, als könnte ich das verstehen was da abläuft.
Nur zur Sicherheit, dass ich mir nicht die doppelte Arbeit mache. Wenn ich mit Microsoft Visual C++ arbeite und dort mit der MFC-Vorlage, dann ist eine solche Funktionalität nicht irgendwie schon "eingebaut"?
Ich sehe da z.B: was von:CViewOpenGl(CWnd* pParent = NULL);Kann man das pParent irgendwie dafür nutzen?
-
hab schon lang nicht mehr mit dem klassenassi vom MFC gearbeitet, aber wenn ich das noch recht in erinnerung habe erbt die CView* von der CWnd, das heist eigendlich das du keinen zugriff auf die funktionen des CViewParent hast sondern nur auf seine CWnd Funktionen.
kann mich aber auch irren

probier es halt einfach mal aus

-
@rT!f@Ct schrieb:
probier es halt einfach mal aus

Einfach sagt sich so einfach wenn man weiß wie. Ich weiß es aber eben nicht besser

Mit pParent. oder pParent-> tut sich jedenfalls nichts beim Intellisense.
Ich versuche ja durch dieses, für mich derzeitige, Wirrwar durchzusteigen.
Alle Tutorials die ich so gelesen habe, gehen zwar auf viele Sachen ein, aber wie ich an Funktionen eines Über-, Unter- oder noch schlimmer Nebengeordneten Dialoges komme, zeigte bisher keines. Entweder zeigen die nur wie man mit drei Mausklicks mal eben einen Dialog anzeigt oder die sind wieder so komplex, dass ich nach dem dritten Satz gar nichts mehr verstehe.
Ich bräuchte mal ein DemoProjekt mit mehreren Dialogen neben und übereinander die gegenseitig Funktionen aufrufen und Variablen austauschen. Gibt es sowas eventuell irgendwo im Netz?
Aller Anfang ist eben schwer. Sorry.
-
Wenn dein Dialog irgendwie mit CWnd verwandt ist, dann kannst du die Methode
CWnd* CWnd::GetParent()aufrufen.
Dazu muss man aber sagen, dass GetParent das in der Hierarchie nächst höhere Fenster zurückgibt. Auch, wenn das selbst ein Child ist.
Sonst gibt es da noch:CWnd* CWnd::GetParentOwner() void CWnd::SetOwner(CWnd* pOwnerWnd)Das Ganze kannst du dann ja passend casten, allerdings muss dann das CWnd-Objekt (oder in deinem Falle das von CWnd abgeleitete) auch noch existieren.
Gruß
eXitus
-
nimm halt mein beispiel was ich dir gegeben habe, und übertrage es auf dein project.
CPrev wäre dein hauptdialog und CNext dein Child bzw. Nebendialog. sobald dein nebendialog den Zeiger des Hauptdialoges hat, kannst du damit arbeiten.
es spielt dabei keine rolle wann (zu welchem zeitpunkt) du den Zeiger des Haupdialoges an den Child/Nebendialog übergibst.das meinte ich mit versuch es halt mal. du kannst nur über try & error lernen. Ich denke es hat noch kein mensch das theoretische auf anhieb so verstanden das er es im ersten versuch fehlerfrei machen konnte. Schon gar nicht wenn man anfänger ist.
Setzt dich hin probier es aus! wenn es dann nicht geht und du gar nicht mehr weiter weist, poste dein problem mit code und einer beschreibung was du machen willst, dann kann man dir weiterhelfen...
Selbst wenn du jetzt den umständlichen weg gehst, wirst du daraus schlauer. es hat auch noch kein anfänger geschafft, auf anhieb ein project zu erstellen, das er im nachhinein nicht x mal umgeschrieben hat.