Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8495
Erhaltene Danke: 453

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Mo 01.03.21 22:09 
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
ausblenden 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
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
if WantStayOnTop then
  FormStyle := fsStayOnTop
  //alternativ: SetWindowPos (Handle, HWND_TOPMOST, -1, -1, -1, -1, SWP_NOMOVE + SWP_NOSIZE)
else
  FormStyle := fsNormal;
  //alternativ: SetWindowPos (Handle, HWND_NOTOPMOST, -1, -1, -1, -1, SWP_NOMOVE + SWP_NOSIZE)


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?

_________________
We are, we were and will not be.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4392
Erhaltene Danke: 944

Win10
C#, C++ (VS 2015/17/19)
BeitragVerfasst: 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.

Für diesen Beitrag haben gedankt: Gausi
Sinspin
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1242
Erhaltene Danke: 112

Win7
DXE2 Prof, Lazarus
BeitragVerfasst: 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.

_________________
Wir zerstören die Natur und Wälder der Erde. Wir töten wilde Tiere für Trophäen. Wir produzieren Lebewesen als Massenware um sie nach wenigen Monaten zu töten. Jetzt rächt sich die Natur und tötet uns.

Für diesen Beitrag haben gedankt: Gausi
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8495
Erhaltene Danke: 453

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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.

_________________
We are, we were and will not be.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8495
Erhaltene Danke: 453

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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:

ausblenden 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 // globales Settings-Objekt
    Params.WndParent := Application.Handle;
end;

procedure TOtherForm.cbStayOnTopClick(Sender: TObject); // (CheckBox.OnClick)
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. :?

_________________
We are, we were and will not be.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4392
Erhaltene Danke: 944

Win10
C#, C++ (VS 2015/17/19)
BeitragVerfasst: Di 02.03.21 23:30 
Ist denn die MyOtherForm auch ein Child der Hauptform?
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8495
Erhaltene Danke: 453

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: 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
ausblenden 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:

_________________
We are, we were and will not be.
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4392
Erhaltene Danke: 944

Win10
C#, C++ (VS 2015/17/19)
BeitragVerfasst: 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).