2010-11-22 10 views
6

Normalement, lorsque vous ouvrez une boîte de dialogue à l'aide de ShowModal, l'exécution du thread en cours s'arrête jusqu'à ce que la boîte de dialogue soit fermée. Je veux afficher une boîte de dialogue Modal, mais continuez l'exécution sur le thread actuel tant que la boîte de dialogue est encore ouverte.Ouverture d'une boîte de dialogue Modal de manière asynchrone dans Delphi

Par "Modal", je veux simplement dire que l'utilisateur ne peut pas interagir avec l'une des autres formes de l'application tant que la boîte de dialogue modale n'est pas fermée.

La fonction Delphi ShowModal fournit une définition légèrement différente de « Modal » à celui que je requiers:

Un formulaire modal est celui où l'application ne peut pas continuer à fonctionner jusqu'à ce que la forme est fermée.

Actuellement, j'ai le code comme ceci:

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

Cela fonctionne, sauf que je peux toujours interagir avec la fenêtre parent (la déplacer, fermer etc)

Comment afficher une formulaire qui empêche l'utilisateur d'interagir avec la fenêtre parente, sans utiliser ShowModal?

Répondre

6

Ouvrez le code source de Delphi \ Source \ VCL \ Forms.pas et ouvrez l'implémentation de ShowModal. Ensuite, apprenez comment cela fonctionne. Je ne peux pas copier le code source ici car c'est une adresse IP de CodeGear, mais vous pouvez le faire vous-même facilement et réutiliser des parties de son code.

+1

Cela semble avoir fonctionné. J'ai divisé ShowModal en deux fonctions; ShowModalNonBlocking et CloseModalNonBlocking. J'ai dû enlever quelques lignes de code qui ne compileraient pas. J'espère qu'il existe une meilleure solution, mais c'est la meilleure suggestion que j'ai trouvée jusqu'ici. – awmross

+0

Je sais que vous ne pouvez pas poster le code, mais pouvez-vous poster des indices, comme "split à la ligne X"? – Mawg

+1

@Mawg La fonction "ShowModalNonBlocking" s'est terminée par un appel à "Show()". Le "CloseModalNonBlocking" a commencé en envoyant un message Windows pour désactiver le dialogue. J'espère que cela pourra aider? – awmross

6

Même avec un formulaire modal ouvert, le thread principal s'exécute toujours (sinon la forme modale ne pourrait pas se repeindre). Cependant, les formulaires modaux ont leur propre boucle d'événements, empêchant l'exécution de la boucle d'événement d'application d'origine. Ils doivent le faire (tout comme les boîtes de message Windows), sinon vous pourriez avoir un événement de retour dans la boucle d'événement principal en créant un autre formulaire modal ou un autre message.

Et ce genre de nier tout le point d'être modal: il ne peut y avoir qu'une seule forme modale ou boîte de message par thread UI.

Vous devez vous poser cette question:

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

ensuite déplacer ces actions dans un thread séparé.

--jeroen

+1

Je ne suis pas d'accord. 'ShowModal' fonctionne en désactivant les autres formulaires, en affichant le nouveau formulaire, puis en exécutant une boucle de message. Je ne vois pas de raison particulière que la boucle de message * doit * appartenir à 'ShowModal'; il pourrait être celui de 'TApplication.Run' à la place. Il peut certainement y avoir plusieurs boîtes de dialogue modales à la fois; montre simplement un autre formulaire à l'intérieur de votre formulaire modal. Un seul peut être * actif *, cependant; les autres sont handicapés. –

+0

@Rob: pensée intéressante; quand une fenêtre modale doit être traitée par l'utilisateur avant qu'il/elle puisse retourner à l'application parente (http://en.wikipedia.org/wiki/Modal_window), comment cette application parente peut-elle démarrer une nouvelle fenêtre modale à partir de un autre endroit que la première fenêtre modale? –

+0

De la même manière que l'application a démarré la première fenêtre modale: Désactiver toutes les fenêtres actives et afficher une autre fenêtre. De préférence, il utiliserait la fenêtre actuellement active comme parent pour le nouveau. –

5

Désactiver votre formulaire parent aussi longtemps que votre boîte de dialogue est visible, cela empêchera les utilisateurs d'interagir il. Vous pouvez également utiliser DisableTaskWindows pour désactiver tous les formulaires et pas uniquement le formulaire parent. Il n'est pas documenté mais vous pouvez voir comment il est utilisé dans TCustomForm.ShowModal dans 'forms.pas'.