2010-11-22 13 views
6

Normalerweise wird beim Ausführen eines Dialogfelds mit ShowModal die Ausführung des aktuellen Threads angehalten, bis das Dialogfeld geschlossen wird. Ich möchte einen Modal-Dialog anzeigen, aber die Ausführung für den aktuellen Thread fortsetzen, während das Dialogfeld noch geöffnet ist.Öffnen eines Modal-Dialogfelds asynchron in Delphi

Mit "Modal" meine ich einfach, dass der Benutzer mit keiner der anderen Formen der Anwendung interagieren kann, bis der modale Dialog geschlossen ist.

Die Delphi ShowModal Funktion liefert eine etwas andere Definition von „Modal“ zu dem einen I erfordern:

A modale Form ist eine, wo die Anwendung nicht weitergeführt werden können, bis die Form geschlossen ist.

Zur Zeit habe ich Code wie folgt:

dialog.Parent:=self; 
dialog.Show; 
// keep doing stuff... 

Dies funktioniert, außer ich noch mit dem übergeordneten Fenster in Wechselwirkung treten können (es bewegen, schließen Sie es etc)

Wie kann ich ein Formular, das den Benutzer daran hindert, mit dem übergeordneten Fenster zu interagieren, ohne ShowModal zu verwenden?

Antwort

6

Öffnen Sie den Quellcode von Delphi \ Source \ VCL \ Forms.pas und öffnen Sie die Implementierung von ShowModal. Dann lerne, wie es funktioniert. Ich kann den Quellcode hier nicht kopieren, da es sich um eine IP-Adresse von CodeGear handelt, aber Sie können dies einfach selbst tun und Teile seines Codes wiederverwenden.

+1

Dies scheint zu funktionieren. Ich habe ShowModal in zwei Funktionen aufgeteilt; ShowModalNonBlocking und CloseModalNonBlocking. Ich musste ein paar Codezeilen entfernen, die nicht kompiliert werden konnten. Ich hoffe, dass es eine bessere Lösung gibt, aber das ist der beste Vorschlag, den ich bisher gefunden habe. – awmross

+0

Ich weiß, dass Sie den Code nicht veröffentlichen können, aber können Sie Hinweise wie "Split in Zeile X" posten? – Mawg

+1

@Mawg Die Funktion "ShowModalNonBlocking" wurde mit einem Aufruf von "Show()" beendet. Das "CloseModalNonBlocking" wurde gestartet, indem eine Windows-Nachricht gesendet wurde, um das Dialogfeld zu deaktivieren. Ich hoffe, das hilft? – awmross

6

Auch bei geöffnetem Modal-Formular wird der Haupt-Thread weiterhin ausgeführt (andernfalls könnte sich das modale Formular nicht selbst neu zeichnen).

Modale Formulare haben jedoch ihre eigene Ereignisschleife, die verhindert, dass die ursprüngliche Anwendungsereignisschleife ausgeführt wird.

Sie müssen (genau wie Windows-Message-Boxen müssen auch), als sonst könnten Sie ein Ereignis zurück in die Main-Event-Schleife schleichen schaffen ein weiteres modales Formular oder eine Messagebox.

Und diese Art negiert den ganzen Punkt des Seins modal: es kann nur ein modales Formular oder eine Messagebox pro UI-Thread geben.

So müssen Sie sich diese Frage stellen:

What actions in the main event loop does this modal form prevent from happening?

Dann diese Aktionen in einem separaten Thread bewegen.

--jeroen

+1

Ich stimme nicht zu. 'ShowModal' funktioniert, indem es die anderen Formulare deaktiviert, das neue Formular anzeigt und dann eine Nachrichtenschleife ausführt. Ich sehe keinen besonderen Grund, dass die Nachrichtenschleife * * zu 'ShowModal' gehören muss; es könnte stattdessen die in 'TApplication.Run' sein. Es kann sicherlich mehrere modale Dialoge gleichzeitig geben; Zeigen Sie einfach ein anderes Formular aus Ihrer modalen Form. Nur einer kann * aktiv * sein; die anderen werden behindert. –

+0

@Rob: interessanter Gedanke; Wenn ein modales Fenster vom Benutzer behandelt werden muss, bevor er zur übergeordneten App (http://en.wikipedia.org/wiki/Modal_window) zurückkehren kann, wie kann diese Eltern-App ein neues, nachfolgendes modales Fenster starten? ein anderer Ort als das erste modale Fenster? –

+0

So wie die App das erste modale Fenster gestartet hat: Alle aktiven Fenster deaktivieren und ein anderes Fenster anzeigen. Vorzugsweise würde es das gerade aktive Fenster als Elternteil für das neue Fenster verwenden. –

5

Deaktivieren Sie Ihre Mutterform, solange Ihr Dialog sichtbar ist, wird dies verhindern, dass Benutzer sie interagieren. Sie können auch DisableTaskWindows verwenden, um alle Formulare und nicht nur das übergeordnete Formular zu deaktivieren. Es ist nicht dokumentiert, aber Sie können sehen, wie es in TCustomForm.ShowModal in 'forms.pas' verwendet wird.

Verwandte Themen