Modeless Dialog...
-
Hallo,
ich erstelle mit dem Wizzard einen Dialog mit zugehöriger Dialog-Klasse.
Wenn ich nun den Dialog folgendermassen benutze, erscheint er korrekt:
CMessageDlg msgDlg; msgDlg.DoModal();
wenn ich den Dialog aber Modeless aufrufe, erscheit er zwar, aber ohne Inhalt:
CMessageDlg msgDlg; //msgDlg.DoModal(); msgDlg.Create(IDD_MSG_DLG); msgDlg.ShowWindow(SW_SHOWNORMAL); Sleep(4000);
Wie kann ich nun den Dialog modeless aufrufen, und gleichzeitig auch noch die Meldung innerhalb sehen?
Vielen Dank,
mfG
Baerbel
-
Probier mal folgendes mit Dir selbst:
SchaueTV(); SchlafeEin();
Nehmen wir weiterhin folgendes für SchaueTV() an:
SchaueTV() { AugenAuf(); DreheKopfInRichtungTV(); Warte100NanoSekunden(); }
Wie lange hast Du nun TV geschaut??
Wenn Du jetzt 100 NanoSekunden antwortest, liegst Du völlig richtig. Aber Windows hatte in 100 Nanosekunden keine Zeit, die Grafik des Dialoges aufzubauen![ Dieser Beitrag wurde am 11.10.2002 um 14:30 Uhr von RenéG editiert. ]
-
Lösung:
Der Trick hierbei ist, den Befehl Warte100Nanosekunden innerhalb SchaueTV so auf den PC umzuschreiben, dass er erst zurückkehrt, wenn der Benutzer den Dialog gesehen und bestätigt hat:class CMessageDlg : public ... { afx_msg OnOk() { // User hat OK gedrückt, ich lösche mich jetzt delete this; } }; // Der Aufruf: CMessageDlg* msgDlg = new CMessageDlg; msgDlg->Create(IDD_MSG_DLG); msgDlg->ShowWindow(SW_SHOWNORMAL);
Soll der Dialog automatisch verschinden, so tue das bitte innerhalb des MessageDialoges. Setze also einen !!! Timer !!! und in der OnTimer-Behandlungsroutine OnOK() aufrufen !
[ Dieser Beitrag wurde am 11.10.2002 um 14:38 Uhr von RenéG editiert. ]
-
Man muss sich auch vorher überlegen, ob das Hauptprogramm weiterlaufen soll, während der Dialog angezeigt wird (vielleicht eine Berechnung), oder aber nix tun soll und der Dialog aber trotzdem automatisch verschwinden soll!
Hier tritt die Lösung mit dem Timer wieder in Kraft, allerdings kann man delete this weglassen, und den Aufruf mit DoModal erledigen
-
Hab gut gelacht....
Aber um in dieser Weise zu antworten:
ZeigeSchild("Bin in 5 min zurück..."); Warte2Min(); ZeigeSchild("Bin in 3 min zurück..."); Warte2Min(); ZeigeSchild("Bin gleich zurück...");
Wie müsste denn meine rechenintensive Funktion aussehen, um Windows genug Zeit zu geben das Fenster zu zeichnen. Ich kann ja wohl kaum die Funktion ShowWindow überschreiben, oder?
mfG
Baerbel
-
ZeigeSchild("Bin in 5 min zurück...");
Warte2Min();
ZeigeSchild("Bin in 3 min zurück...");
Warte2Min();
ZeigeSchild("Bin gleich zurück...");Hm, da hast Du die Funktion ShowWindow wohl falsch verstanden, denn diese macht folgendes:
ShowWindow( "Show") { SchildaufNormalzustandbringen(); // Visible und Grösse != 0 SageDemBenutzerDassSchildfertigist(); // Invalidate() wird aufgerufen }
So, nun sagt Invalidate aber nicht, dass das Schild gezeigt werden soll, sondern nur, dass es übermalt werden muss! Danach kehrt die Funktion zurück, und der Maler, der es eigentlich malen soll, bekommt den Befehl Schlafen() !!
Kann also so net funktionieren. Um das Bild zu malen, muss
msgDlg.UpdateWindow() aufgerufen werden, welches WM_PAINT in die Nachrichtenschlange setzt!
Wenn jetzt das Sleep erfolgt, passiert aber immernoch nix, weil zwar der Auftrag da ist, aber die Message nicht verarbeitet werden kann, weil er ja schläft!Fazit: Sleep ist eine schlechte Funktion unter Windows! Es ist immer besser, Timer zu verwenden!
-
Das Sleep ist ja in diesem Zusammenhang nur eingefügt, um eine Berechnung zu simulieren. Die Situation ist aber die selbe, wenn ich statt zu Schlafen halt die Primzahlen von 0 bis 1000 brechne.
Die Verwendung des Timer's hab ich in dem Zusammenhang aber noch nicht verstanden...Was soll denn der Timer tun?Wärend dieser Thread rechnet oder schläft kann er also nicht die Messagequeue abarbeiten.
Also muss ein neuer Thread her, oder?
Und das nur um Nachricht auf dem Bildschirm anzuzeigen?
Nochmal zum Verständniss, mir schwebt in etwa sowas vor:void calcPrim(){ CMessageDlg msgDlg; msgDlg.ZeigeNachricht("Rechnung beginnt"); primvonbis(0,100); msgDlg.ZeigeNachricht("Bischen Geduld lieber User, es ist gleich soweit"); primvonbis(100,1000); msgDlg.ZeigeNachricht("Rechnung abgeschlossen"); }
Mit einem modalen Dialog ist das kein Problem, nur leider muss der Dialog immer erst geschlossen werden, um ein Weiterarbeiten zu ermöglichen.
Ist mir noch zu helfen?
mfG
Baerbel[ Dieser Beitrag wurde am 11.10.2002 um 15:35 Uhr von Baerbel editiert. ]
-
Klar geht das, hierfür ist Dein Beitrag Nr. 1 völlig ausreichend, nur muss hinter jedem Befehl, der was an der Anzeige des MessageDlgs ändert, der Befehl msgDlg.UpdateWindow() erfolgen. Folgende Einschränkung gilt: Die Messageverarbeitung ist für Benutzereingaben nicht aktiv. Sollen während der Berechnung Benutzereingaben erfolgen, dann ist ein eigener Thread zu bevorzugen
-
Na ich bin ein Trottel.
Wenn ich statt dem testhalber eingefügtenSleep(2000);
ein
for (int n=0;n<100;n++) Sleep(20);
benutze, funktioniert alles genau wie ich mir das vorgestellt habe.
Danke für die Hilfe. Das nächste mal schildere ich mein Problem genauer, dann kommt es zu solchen Missverständnissen nicht...
Soweit
mfG
Baerbel