AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

AlwaysOnTop mit mehreren Formularen

Ein Thema von Dalai · begonnen am 8. Mai 2020 · letzter Beitrag vom 14. Mai 2020
Antwort Antwort
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.573 Beiträge
 
Delphi 12 Athens
 
#1

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 01:47
Das Property FormStyle = fsStayOnTop macht eigentlich genau das
"genau" ist trifft es nicht so ganz genau.

Beim Ändern wird die innere Form komplett neu generiert, anstatt nur die eine Option zu ändern.


In Windows 10, da ist und bleibt zwar bei beiden Forms die Option aktiv (siehe Caption), aber nur der Erste, welcher diese Option setzt, ist wirklich ganz oben.

Unabhängig vom ExStyle, gibt es ja auch nur eine Liste mit den Z-Positionen und da kann nur einer ganz oben sein,
aber vielleicht wurde das früher im Windows mal anders behandelt.

Eventuell gibt es auch noch einen Unterschied bei MultiMonitor-Systemen, wenn man jemanden glauben mag, falls man z.B. nach Bei Google suchenmultiple HWND_TOPMOST sucht.
Hab hier jetzt nur einen Monitor aktiv (bzw. ist gespiegelt), aber könnte es nächste Woche mal ausprobieren.

Delphi-Quellcode:
uses Unit2;

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
  TForm2.Create(Self).Show;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  //SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_TOPMOST);
  // theoretisch, aber ändern via SetWindowLong, siehe https://docs.microsoft.com/de-de/windows/win32/winmsg/extended-window-styles
  SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Caption := BoolToStr(GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0, True);
end;
Delphi-Quellcode:
implementation

uses Unit1;

procedure TForm2.FormActivate(Sender: TObject);
begin
  SetWindowPos(Handle, {Form1.Handle}HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TForm2.Timer1Timer(Sender: TObject);
begin
  Caption := BoolToStr(GetWindowLong(Handle, GWL_EXSTYLE) and WS_EX_TOPMOST <> 0, True);
end;
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.771 Beiträge
 
Delphi 12 Athens
 
#2

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 08:11
Beim Ändern wird die innere Form komplett neu generiert, anstatt nur die eine Option zu ändern.
Wo siehst du das denn?
Delphi-Quellcode:
  
  if FFormStyle <> Value then
  begin
    if ((Value = fsNormal) and (FFormStyle = fsStayOnTop)) or
       ((Value = fsStayOnTop) and (FFormStyle = fsNormal)) then
    begin
      FFormStyle := Value;
      if not (csDesigning in ComponentState) and HandleAllocated then
        SetWindowPos(Handle, HWND_STYLE[FFormStyle = fsStayOnTop], 0, 0, 0, 0,
          SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE or SWP_NOOWNERZORDER);
    end
    else
      ...
    end;
  end;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.771 Beiträge
 
Delphi 12 Athens
 
#3

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 09:22
Wenn du sagst, die Fenster verlieren ihre TOPMOST Eigenschaft, wie äußert sich das? Sind plötzlich andere Forms deiner eigenen Anwendung über diesen (eigentlich TOPMOST) Forms oder sind nur Fenster einer anderen Anwendung darüber?
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.573 Beiträge
 
Delphi 12 Athens
 
#4

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 16:42
Windows 10 und Delphi 10.3, gestern ausprobiert: Nur das erste TopMost-Fesnter ist immer oben,
aber in den Fenstereigenschaften steht es dennoch bei Beiden drin. (Dachte vielleicht Windows schaltet es beim anderen Fenster ab, bzw. ignoriert das Setzen im Zweiten)

Mir war so, als wenn da das Fenster immer so richtig schön kurz wegblinkte. Vielleicht wurde es ja inzwischen geändert.
Aber ich geb mit Stolz zu, dass ich seit vielen Jahren mich erfolgreich von TopMost verabschiedet hab, da es mehr Arbeit machte, als Freude zu bereiten.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.771 Beiträge
 
Delphi 12 Athens
 
#5

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 17:13
Grundsätzlich kann ja auch nur ein Fenster oben sein. TOPMOST heißt ja auch nur: das Fenster ist über den Fenstern, die nicht TOPMOST sind. Innerhalb von TOPMOST und NON-TOPMOST gibt es natürlich jeweils eine Reihenfolge.

Es geht nur darum, dass beide Formulare über den Fenstern anderer Anwendungen liegen sollen.
Das wird nur gehen, wenn die anderen Anwendungen nicht dasselbe vorhaben und ihre eigenen Fenster auch als TOPMOST deklarieren.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.573 Beiträge
 
Delphi 12 Athens
 
#6

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 21:31
Es kommt drauf an, wie man es sieht/auslegt

TopMost = über ALLEM (da ginge nur Einer, so ala Highlander)
TopMost = über allem, was nicht TopMost ist

In einem Programm/Thread bekomm ich jetzt auch nur 1 Fenster, was immer oben bleibt,

aber starte ich das Programm doppelt (pro Programm/Thread nur ein Fenster), dann geht es auch mehrfach.
> das was den Fokus hat, jeweils ganz oben, aber alle immer über den normalen Fenstern
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.573 Beiträge
 
Delphi 12 Athens
 
#7

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 22:18
siehe #5 ?

[edit]
Hab's aber grad nochmal probiert ... ich glaub Delphi bzw. die VCL ist Schuld.

Vorhin falsch geguckt, denn so ist es aktuell in Windows 10 + Delphi 10.3:
* das zweite Fenster ist immer über dem Ersten
* wären Beide gleich (StayOnTop oder nicht), müsste jeweils das Aktive oben sein
* vermutlich irgendwas in Richtung PopupMode, aber das steht (standardmäßig) eigentlich auf pmNone :grueble:

[edit2]
Delphi-Quellcode:
procedure TCustomForm.CreateParams(var Params: TCreateParams);
...
        case LPopupMode of
          pmNone:
            begin
              if Application.MainFormOnTaskBar then
              begin
                // FCreatingMainForm is True when the MainForm is
                // being created, Self = Application.MainForm during CM_RECREATEWND.
                if FCreatingMainForm or (Self = Application.MainForm) then
                  WndParent := 0
                else
                  if Assigned(Application.MainForm) and Application.MainForm.HandleAllocated then
                  begin
                    WndParent := Application.MainFormHandle;
                    if WndParent = Application.MainForm.Handle then
                    begin
                      if Application.MainForm.PopupChildren.IndexOf(Self) < 0 then
                        Application.MainForm.PopupChildren.Add(Self); <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                      FreeNotification(Application.MainForm);
                    end;
                  end
                  else
                    WndParent := Application.Handle;
              end
              else
              begin
                WndParent := Application.Handle;
                SetWindowLong(WndParent, GWL_EXSTYLE, GetWindowLong(WndParent, GWL_EXSTYLE) and not WS_EX_TOOLWINDOW);
              end;
            end;
          pmAuto:
            begin
              if FCreatingMainForm then
                WndParent := 0 // A main form can't be parented to another form
              else
Keine Ahnung wer auf diese bescheuerte Idee gekommen ist auch bei NONE etwas zu machen.

Lösung:
Und statt OnActivate, ist sowieso CreateWnd besser. (auch wenn Beides geht)
Delphi-Quellcode:
type
  TForm3 = class(TForm)
    procedure FormCreate(Sender: TObject);
  protected
    procedure CreateWnd; override;
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

procedure TForm3.CreateWnd;
begin
  inherited;
  SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
  PopupMode := TPopupMode(9);
end;
[Edit3]
Oder Application.OnGetMainFormHandle benutzen und dort HWND(-1) zurückgeben.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 9. Mai 2020 um 22:48 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.771 Beiträge
 
Delphi 12 Athens
 
#8

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 22:41
Es kommt drauf an, wie man es sieht/auslegt

TopMost = über ALLEM (da ginge nur Einer, so ala Highlander)
TopMost = über allem, was nicht TopMost ist
Wohl eher nicht wie man das sieht/auslegt, sondern wie MS das implementiert hat.

Zitat:
HWND_TOPMOST: Places the window above all non-topmost windows. The window maintains its topmost position even when it is deactivated.
Um ein TOPMOST Fenster über alle anderen (auch TOPMOST) zu legen, kann man ein SetWindowPos mit HWND_TOP senden. Das platziert ein Fenster so weit vorn wie möglich - bei einem TOPMOST Fenster halt ganz nach vorn. Das hält aber auch nur solange bis ein anderes TOPMOST Fenster (z.B. einer anderen Anwendung) sich davor legt.

Man kann auch noch mit PopupParent experimentieren. Ist das nicht gesetzt, wird implizit das MainForm verwendet. Das hat aber nur Auswirkungen auf die eigenen Anwendung.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.684 Beiträge
 
Delphi 5 Professional
 
#9

AW: AlwaysOnTop mit mehreren Formularen

  Alt 9. Mai 2020, 21:47
Das wird nur gehen, wenn die anderen Anwendungen nicht dasselbe vorhaben und ihre eigenen Fenster auch als TOPMOST deklarieren.
Wie ich bereits schrieb, ist mir das "Highlander-Prinzip" in diesem Fall bekannt. Ist das Problem denn mit meinem Testprogramm nachvollziehbar, wenn die beiden Formulare nebeneinander positioniert sind? Denn wie gesagt interessiert mich nicht, ob Formular 2 der Anwendung über Formular 1 derselben Anwendung liegt, denn das passiert nicht und das teste ich auch nicht. Wichtig für mich ist ausschließlich, dass beide Formulare meiner Anwendung (die immer nebeneinander liegen) über den Fenstern anderer Anwendungen (ohne TOPMOST) liegen. Es geht da auch um nichts Großes, das eine Formular ist 65x31 Pixel, das andere ~170x20 Pixel.

Zwischenzeitlich hab ich das zweite Form in eine eigene Anwendung überführt (weil ich für ein anderes Projekt fix eine Lösung brauchte), aber ich bin dennoch an einer Lösung innerhalb einer Anwendung interessiert.

Grüße
Dalai
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz