26 Stimmen

Warum ein eigenes Fenster in MessageBox.Show verwenden?

MessageBox.Show hat Formen wie MessageBox.Show( ownerWindow, .... ).

Was bringt mir die Zuweisung eines eigenen Fensters?

26voto

Jeffrey L Whitledge Punkte 55524

Ein Meldungsfeld ist ein modales Formular, was bedeutet, dass das übergeordnete Fenster deaktiviert ist, bis das Meldungsfeld geschlossen wird.

Wenn eine Show()-Überladung aufgerufen wird, die keinen Besitzer-Identifikator annimmt, wird normalerweise automatisch ein übergeordnetes Formular ausgewählt. Ich kann in der Dokumentation nichts finden, was beschreibt, wie dieses Formular ausgewählt wird, aber meine Erfahrung ist, dass, wenn das Nachrichtenfeld innerhalb des GUI-Threads (d.h. des Haupt-Threads oder des Message-Pump-Threads) angezeigt wird, das aktive Fenster für diesen Thread als Elternteil ausgewählt wird.

Andere Threads können Nachrichtenfelder ohne übergeordnetes Formular erstellen. Dies könnte eine schlechte Situation sein, weil es hinter dem aktiven Fenster sitzen könnte und der Benutzer nicht einmal weiß, dass es da ist, bis er das Programm schließt. Um dies zu vermeiden, können Sie das Handle des Hauptfensters der Anwendung an die Show-Methode übergeben, wodurch dieses Fenster für die Dauer des Nachrichtenfensters deaktiviert wird.


HINZUFÜGEN: Ich habe darüber nachgedacht, und jetzt bin ich mir nicht mehr so sicher. Der Ausschnitt aus dem Reflektor, den Sie unten angegeben haben, lässt mich denken, dass das Thema vielleicht keine Rolle spielt. (Ich habe gesagt, dass ich nichts in der Dokumentation finden konnte!)

Ich müsste mir den Code noch einmal ansehen, um sicherzugehen, aber ich denke, dass die Meldungsfelder, die ich hinter dem Hauptformular verloren habe, möglicherweise tatsächlich benutzerdefinierte Meldungsfeldformulare waren, in diesem Fall ist meine Erfahrung fehlerhaft, und Sie müssen niemals einen übergeordneten Formularparameter angeben.

Entschuldigung für die Verwirrung.

Ich empfehle, diesen Parameter nur dann zu verwenden, wenn Sie ein anderes als das aktive Fenster als Hauptformular benötigen.

3voto

Nir Punkte 28685

Durch das Festlegen des Eigentümers wird der Eigentümer deaktiviert, solange das Nachrichtenfeld geöffnet ist.

Wenn Sie den Eigentümer nicht festlegen, kann der Benutzer auf etwas anderes klicken oder sogar den Eigentümer schließen, während das Nachrichtenfeld geöffnet ist. Wenn dann das Nachrichtenfeld geschlossen wird und der Code nach dem Aufruf von MessageBox.Show ausgeführt wird, kann sich Ihr Programm in einem unbekannten Zustand befinden - oder wenn der Eigentümer geschlossen wurde, führen Sie jetzt Code in einem Fenster aus, das nicht mehr existiert, und alle Aufrufe von WinForms- oder WPF-Methoden (oder auch von WinAPI und anderen Frameworks) werden wahrscheinlich zu einem Absturz führen.

3voto

binki Punkte 6868

Auf der Grundlage von Tests und diese andere Antwort wählen, wählt .net automatisch das aktuell fokussierte Fenster im gleichen Thread wie Ihr MessageBox.Show() anrufen. Um das richtige Verhalten zu erreichen, müssen Sie muss stellen Sie sicher, dass Sie die MessageBox aus dem gleichen Thread wie dieses Fenster y das Fenster angeben, das MessageBox logisch verbunden ist mit als seine owner . A MessageBox blockiert nur modal die Eingabe in andere Form s auf dem Thread, von dem aus er gestartet wird. Dies hängt wahrscheinlich damit zusammen, wie MessageBox macht sich selbst modal (vielleicht fängt es Nachrichten ab, die an den aktuellen Thread gerichtet sind, und lässt nur einige Nachrichten an andere Fenster als sich selbst durch?) Die Auswirkung der modalen Blockierung von Eingaben ist, dass der Benutzer nicht in der Lage ist, diese Fenster oder die darin enthaltenen Steuerelemente zu fokussieren, und der Versuch, dies zu tun, erzeugt den "Ding"-Ton. Wenn der Besitzer nicht angegeben ist, wird außerdem die MessageBox wählt automatisch das aktive Fenster des aktuellen Threads aus. Wenn das derzeit aktive Fenster von einem anderen Thread (oder einer anderen Anwendung!) stammt, wird die MessageBox hat keinen Besitzer. Das bedeutet, dass es einen eigenen Eintrag in der Taskleiste erhält: Es verhält sich wie ein eigenes, eigenständiges Fenster. Der Benutzer kann andere Fenster in Ihrer Anwendung aufrufen (auch wenn der Benutzer nicht mit ihnen interagieren kann). Das kann dazu führen, dass Ihr Programm nicht mehr auf Benutzereingaben reagiert und der Benutzer verwirrt ist, weil der Benutzer das Hauptfenster Ihrer Anwendung irgendwie hochgezogen hat, nachdem der Dialog angezeigt wurde. Wenn der Eigentümer jedoch richtig eingestellt ist, führt der Versuch, das Hauptfenster anzuheben, dazu, dass die MessageBox angehoben werden und blinzeln.

Damit dies alles mit untergeordneten Fenstern gut funktioniert, stellen Sie sicher, dass jedes untergeordnete Fenster seine Owner Eigenschaft gesetzt. Dies geschieht automatisch, wenn Sie ShowDialog() (wodurch Ihre benutzerdefinierte Form modal (und tun passieren seine owner Parameter in denselben Fällen, in denen Sie owner a MessageBox.Show() )).

Jetzt besteht die meiste Winforms-Programmierung aus dem Schreiben von Code direkt in Ereignis-Handlern innerhalb einer Form Unterklasse. Wenn Sie Winforms-Ereignishandler schreiben, können Sie von vielen Dingen ausgehen. Erstens sollten Sie niemals einen Aufruf an this.Invoke() als Top-Level-Anweisung in einem GUI-Ereignishandler, da solche Handler immer auf demselben Thread laufen wie der Form Unterklasse wurde erstellt am. Zweitens, für viele (aber nicht alle) dieser Handler, können Sie davon ausgehen, dass die Form den Fokus hat (und somit automatisch von MessageBox.Show() als sein Besitzer). Wenn Sie zum Beispiel Code innerhalb des Click-Event-Handlers einer Schaltfläche schreiben (der möglicherweise button1_Click ), können Sie sicher davon ausgehen, dass das Formular fokussiert ist (weil der Aufruf von PerformClick() auf dem Formular eines anderen Button ist schlechte Praxis). Allerdings ist eine Timer.Tick kann auch dann auftreten, wenn Ihr Formular nicht fokussiert ist. Also, im Fall von Timer.Tick gibt es keine Notwendigkeit Invoke() (wie jeder andere Winforms-Ereignishandler auch) aber dort est ein Bedürfnis zu spezifizieren owner . Dieser letzte Fall ist schwieriger zu erkennen, da der Entwickler seine Anwendung nicht fokussiert haben muss, um zu bemerken, dass sich ein in diesem Fall angezeigtes Dialogfeld etwas anders verhält, als wenn seine Anwendung fokussiert ist. Also, angeben. owner wann immer Sie Folgendes verwenden müssen Invoke() oder wenn es möglich ist, dass das Ereignis ausgelöst wird, wenn das Fenster nicht fokussiert ist. Dieser Leitfaden gilt für den Aufruf von MessageBox.Show() y Form.ShowDialog() .

Das meiste von dem, was ich hier bespreche, ist das Ergebnis von Gemurkse während Sie die anderen Antworten lesen.

1voto

jyoung Punkte 4963

Es stellt sich heraus, dass der Besitz von Fenstern nicht transitiv ist. In dem Fall, in dem Sie ein Formular haben, das eine MessageBox erzeugt, muss die MessageBox.Show den Parameter ownerWindow verwenden. Das ursprüngliche Formular sollte als Eigentümerfenster der MessageBox festgelegt werden.

1voto

Felinis Punkte 47

Aufruf von MessageBox.Show(frmMain,"a message","a title") fügt das Formular TextDialog zur Anwendung der Application.OpenForms() Formularsammlung, zusammen mit dem Formular frmMain Main selbst. Es bleibt erhalten, nachdem Sie die Messagebox geschlossen haben.

Ich habe gerade 14 davon entdeckt, als ich anrief btnOK_Click() und setzen Sie einen Haltepunkt.

Als ich anrief frmMain.Close() um das Hauptformular zu schließen, ist nichts passiert. frmMain wird erst geschlossen, wenn alle 14 Application.OpenForms ebenfalls geschlossen sind, oder Sie müssen Application.Exit() .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X