12 Stimmen

Delphi, möglich zu machen, ein Formular modal zu bestimmten übergeordneten Form nur?

Ich habe eine Anwendung, wo es ein Haupt-Hintergrund-Formular, von dort Benutzer kann nur nicht-modale Formulare, die verschiedenen Teil des Systems unterhält. Die nicht-modale Formulare überschreibt die CreateParams-Methode, so dass jeder eine Schaltfläche in der Start-Taskleiste anzeigt:

procedure TfmMaterialsPlanning.CreateParams(var Params: TCreateParams);
begin
   inherited;
   //create a new window on the task bar when this form is created
   Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
end;

So kann ein Benutzer ein nicht-modales Formular öffnen, das "Äpfel" verwaltet, ein anderes nicht-modales Formular, das "Orangen" verwaltet, und die Startmenüleiste verwenden, um einfach zwischen beiden zu wechseln.

Wenn sie jedoch ein modales Formular vom "Apfel"-Formular aus öffnen, z. B. um Optionen, Einstellungen usw. festzulegen, können sie die "Orangen"-Formulare nicht verwenden, bis sie das modale Formular schließen.

Ist es möglich, ein modales Formular nur für das übergeordnete Formular modal zu machen? Wenn sie also das Optionsformular von Apple öffnen, können sie das Wartungsformular von Apple nicht verwenden, aber sie können das Wartungsformular von Orangen verwenden?

8voto

mghie Punkte 31618

Wenn Sie einen Blick auf den Quellcode von TCustomForm.ShowModal() werfen, werden Sie sehen, dass die VCL nicht den Windows-API-Aufruf zum Anzeigen modaler Dialoge verwendet, sondern stattdessen alle anderen Formulare in der Anwendung deaktiviert, während das modale Formular angezeigt wird. Sie können natürlich dasselbe versuchen, indem Sie einfach den modalen Dialog anzeigen(), dann das übergeordnete Formular deaktivieren und es dann wieder aktivieren, nachdem der modale Dialog geschlossen wurde. Es muss eine zentrale Stelle geben, an der Sie den Überblick über form-modale Dialoge, die Formulare, die wieder aktiviert werden müssen, usw. behalten. Sie sollten jedoch gründlich testen, ob der Code tatsächlich das tut, was Sie wollen, auch wenn Sie zwischen Anwendungen hin- und herwechseln, wenn Sie die Anwendung minimieren und so weiter.

Davon abgesehen halte ich das für keine gute Idee. Es bricht alle Annahmen, die ein Windows-Benutzer über das Verhalten von Anwendungen macht. Anders als in Mac OS X gibt es in Windows keine Unterscheidung zwischen anwendungsmodalen und formularmodalen Dialogen, und man sollte sich an das Verhalten halten, das mit der Plattform, für die man programmiert, konsistent ist.

Wahrscheinlich gibt es eine bessere Möglichkeit, die Benutzeroberfläche zu strukturieren. Werfen Sie einen Blick auf die entsprechende Seite für Dialogfelder in den "Windows User Experience Interaction Guidelines". Modale Dialoge sollten so weit wie möglich vermieden werden, die verlinkten Richtlinien zeigen für viele Anwendungsfälle bessere Alternativen. Wenn Sie die Verwendung von modalen Dialogen einschränken, benötigen Sie die formularmodalen Dialoge vielleicht nicht mehr.

2 Stimmen

Wenn der Benutzer über zwei Schaltflächen in der Taskleiste verfügt, entspricht es durchaus den UI-Richtlinien, dass ein modales Dialogfeld, das von einem dieser beiden Fenster angezeigt wird, das andere Fenster nicht blockiert. Die Tatsache, dass die beiden Taskleistenschaltflächen von demselben Prozess gehostet werden, ist für den Benutzer irrelevant. Ich würde sogar argumentieren, dass ein modaler Dialog, der beide Fenster blockiert, unangemessen ist. Wie auch immer, Daniel verweist auf eine Lösung, die funktioniert.

3voto

Daniel Luyo Punkte 1316

Dieser Beitrag enthält einen netten Trick, um Ihre Bedürfnisse zu erfüllen: http://blogs.teamb.com/deepakshenoy/2006/08/21/26864

Die Zusammenfassung besteht darin, das gewünschte nichtmodale Fenster wieder zu aktivieren, wenn ein modales Fenster es deaktiviert hat.

0 Stimmen

Funktioniert prima! Wahrscheinlich ist es eine gute Idee, etwas zusätzliche Logik hinzuzufügen, damit das Formular nicht gesendet wird. WM_REENABLED zu sich selbst, wenn es einen eigenen modalen Dialog anzeigt.

0voto

Aikislave Punkte 636

Nebenbei bemerkt (obwohl es eine Menge Arbeit wäre), ist eine andere Herangehensweise an dieses Problem der Weg, den Google Chrome eingeschlagen hat, wo jede "Registerkarte" ein separater Prozess ist, aber dem Benutzer als eine einzige integrierte Anwendung erscheint.

Auch wenn mit diesem Ansatz das Gewünschte erreicht wird, muss ich dem obigen Kommentar zustimmen, dass dies die Annahmen und Erwartungen des Benutzers in Bezug auf das modale Verhalten brechen würde.

0voto

Argalatyr Punkte 4639

Könnten Sie nicht denselben Effekt erzielen, indem Sie verhindern, dass das Formular "Äpfel" den Fokus annimmt, während das untergeordnete Formular geöffnet ist?

-1voto

Vegar Punkte 12511

Dies ist möglich, wenn Sie jedes nicht-modale Formular in einem eigenen Thread erstellen. Jedes modale Formular wird dann den Thread blockieren, zu dem es gehört.

Edit: Das sollte möglich sein, auch wenn die vcl nicht thread-sicher ist. Bitte werfen Sie einen Blick auf Alexeys Erklärung wie dies erreicht werden kann:

Wenn Sie also eine Reihe von Formularen haben, die in einem separaten Thread laufen sollten, dann packen Sie sie in eine dll, kompilieren Sie sie ohne Pakete und benutzen Sie sie! Es wird funktionieren und es wird thread-sicher sein.

0 Stimmen

Bei Verwendung der VCL ist dies unmöglich, da sie nur von einem Thread aus verwendet werden kann, wenn man GUI-Sachen macht.

0 Stimmen

Stimmt, aber dann hat jede DLL ihre eigene Kopie der gesamten VCL und ihr eigenes Anwendungsobjekt. IMO ist dies kaum besser, als wenn man von vornherein mit verschiedenen ausführbaren Dateien arbeitet.

0 Stimmen

Ich weiß nicht, warum Robo die Dinge so will, wie er sie beschreibt. Er fragt, ob es möglich ist, und ich sage, es ist möglich. Du sagst, es ist nicht möglich, ich sage, du irrst dich...

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