Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Z-Order von Fenstern
Gausi - Mo 01.03.21 22:09
Titel: Z-Order von Fenstern
Ich bekomme hier eine kleine Krise mit der Z-Reihenfolge von Fenstern einer Anwendung (Windows, VCL).
Grundsätzlich ist das Verhalten in neueren Delphi-Versionen ja so, dass Nebenfenster vor der MainForm angezeigt werden, auch wenn sie nicht den Fokus haben. Das ist manchmal sinnvoll, manchmal aber auch nicht - da möchte man durchaus, dass eine offene Nebenform wieder in den Hintergrund rückt, wenn man in die MainForm klickt.
Dieses alte Verhalten kann man ja erreichen mit
Delphi-Quelltext
1: 2: 3: 4: 5:
| procedure TMyOtherForm.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); Params.WndParent := Application.Handle; end; |
Jetzt möchte ich dem User aber zur Laufzeit die Wahl lassen, ob er diese Nebenform vor dem Hauptformular festpinnt, oder eben nicht. Das probiere ich mit
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| if WantStayOnTop then FormStyle := fsStayOnTop else FormStyle := fsNormal; |
Beides funktioniert nicht, wie gewünscht.
Mit StayOnTop bzw. HWND_TOPMOST
- MyOtherForm liegt auch über allen anderen Anwendungen. Es soll aber nur über der MainForm liegen.
- MyOtherForm liegt auch über einem OpenDialog, der von MyOtherForm aus geöffnet werden soll. Da der OpenDialog (wie üblich) Modal ist, kann man z.B. die Checkbox für "StayOnTop" in MyOtherForm auch nicht deaktivieren. D.h. ich habe MainForm->OpenDialog(modal, aber ganz oder teilweise verdeckt)->OtherForm(deaktiviert, aber im Vordergrund)
Interessanterweise bewirkt auch fsStayOnTop, dass das Fenster vor allen Anwendungen liegt. Ich dachte eigentlich, dass das mal nur "Top der Application" war ... :gruebel: Zumindest mit der modifizierten CreateParams ist das so. Ohne die Modifizierung hat auch mein StayOnTop-Code keinerlei Auswirkungen mehr.
Ohne StayOnTop
- Beim öffnen des OpenDialoges rutscht MyOtherForm in den Hintergrund, d.h. OtherForm->MainForm->OpenDialog statt (wie eigentlich logisch) MainForm->OtherForm->OpenDialog
Bekomme ich das ohne irgendwelche Hampeleien (im OnDeactivate etc.) hin, dass eine Form vor der Mainform bleibt (auch wenn die MainForm den Eingabefokus bekommt), aber hinter eventuell zusätzlich geöffneten Dialogen? Oder aber (zur Laufzeit umstellbar) eben nicht?
Th69 - Di 02.03.21 09:31
StayOnTop erscheint mir hier der falsche Weg zu sein, denn dieses gilt (wie du selbst erkannt hast) global für alle Desktop-Windows.
Für Fenster, welche immer oberhalb eines Hauptfensters erscheinen sollen (aber hinter modalen Dialogen), gibt es "Tool Windows":
Tool window stay on top [
http://www.delphigroups.info/2/b9/412468.html].
Sinspin - Di 02.03.21 10:03
Ich habe bei mir die ganzen alten SetWindowPos und CreateParams rausgeschmissen. Seitdem ist alles viel besser.
Genau, die Tool Windows, die verwendet die IDE ja auch und da klappt es prima.
Gausi - Di 02.03.21 10:08
Danke, schau ich mir mal an. Ein kurzer Schnelltest war negativ, d.h. es funktioniert leider immer noch nicht. Muss ich heute Abend mal in Ruhe an einem Testprojekt austüfteln. Kann sein, dass ich noch an anderer Stelle anderen Code drin habe, der sich damit beißt. Oder es sind die VCL-Styles, oder der Splashscreen beim Start, oder ...
Zumindest weiß ich nun, wo ich ansetzen muss: PopupMode und PopupParent.
Gausi - Di 02.03.21 22:14
Ich glaube, die Dokumentation stimmt da nicht ganz mit dem tatsächlichen Verhalten überein, oder es fehlt noch der Hinweis zu
MainFormOnTaskbar. :?
Wenn PopupMode zur Laufzeit geändert werden soll, wird eine Neuerstellung des Fensters notwendig. Und da ich die Hampelei mit PopupMode einfach einfach nicht hin bekomme (und solange MainFormOnTaskbar True ist, hat das anscheinend ohnehin kaum Auswirkungen?), mache ich das jetzt so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| procedure TOtherForm.CreateParams(var Params: TCreateParams); begin inherited CreateParams(Params); if not MainOptions.OtherFormStayOnTop then Params.WndParent := Application.Handle; end;
procedure TOtherForm.cbStayOnTopClick(Sender: TObject); begin MainOptions.OtherFormStayOnTop := cbStayOnTop.Checked; RecreateWnd; end; |
Die ggf. ungünstige Z-Order des OpenDialoges scheint ein Bug mit den VCL-Styles zu sein. Ohne Styles ist das wie gewünscht, mit Styles fällt die OtherForm in den Hintergrund. :?
Th69 - Di 02.03.21 23:30
Ist denn die MyOtherForm auch ein Child der Hauptform?
Gausi - Mi 03.03.21 20:37
Da verstehe ich jetzt nicht ganz, was damit gemeint ist. Aber ob ich die Nebenform automatisch erzeugen lasse, oder per
Delphi-Quelltext
1: 2:
| if not assigned(ChildForm) then ChildForm := TChildForm.Create(self); |
manuell erzeuge, oder per
Application.CreateForm(...), ändert nichts an dem Verhalten, dass ich ohne Modifikation der CreateParams nicht weiterkomme ... :gruebel:
Th69 - Do 04.03.21 10:10
OK, ich wollte nur wissen, welchen Owner (und damit auch Parent) du beim Anlegen der Form angegeben hast - hättest ja auch nil setzen können.
Teste das gesamte Verhalten am besten mal in einem neuen Projekt (bevor du es in dein bestehendes Projekt einbaust).
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2024 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!