Hi zusammen,
ich habe ein Problem mit dem Ereignis TForm.OnWindowStateChange. Dieses
wird bei mir mehrfach ausgelöst - der Grund erschließt sich mir auf den
1. Blick nicht. (Bug in LCL mag ich nicht ausschließen, aber ich bin
doch nicht der erste, der das merken müßte...)
Was ich will:
Wenn das Fenster (bei mir einziges Fenster des Programms, keine
Children) minimiert wird, dann soll es ausgeblendet werden und ein
TrayIcon erscheinen. Wenn ich auf das TrayIcon klicke, dann soll das
Fenster wieder erscheinen.
Was ich tue:
procedure TMainform.FormWindowStateChange(Sender: TObject);
var ws: TWindowState;
begin
ws:=WindowState;
if ws=PrevWindowState then exit;
WriteLn(GetTickCount64:20, ' ws: ', ws, ' prev: ', PrevWindowState);
case ws of
wsMinimized : OnMinimize;
wsNormal,
wsMaximized : ;
end;
PrevWindowState:=ws;
end;
procedure TMainform.OnMinimize;
var trayicon: TTrayIcon;
begin
if Data.ProperShutdown then exit;
if Data.MinimizeToTray then begin
trayicon:=Data.TrayIcon;
trayicon.OnClick:=@OnTrayIconClick;
trayicon.Show;
Application.ProcessMessages;
self.Hide;
end;
end;
procedure TMainform.OnRestore;
var trayicon: TTrayIcon;
begin
if Data.ProperShutdown then exit;
if Data.MinimizeToTray then begin
trayicon:=Data.TrayIcon;
trayicon.OnClick:=nil;
trayicon.Hide;
Application.Restore;
self.Show;
self.WindowState:=wsNormal;
Application.ProcessMessages;
end;
end;
OnRestore wird vom TrayIcon ausgelöst
Was passiert:
Selten funktioniert es. Ganz oft blitzt das Fenster kurz auf und
verschwindet gleich wieder und das TrayIcon erscheint sofort wieder -
als ob es nach dem Restore gleich wieder minimiert würde.
Was genau passiert:
Habe mir mal eine Debug-Ausgabe gebastelt, um das Verhalten
nachvollziehen zu können. Der Tray-Handler wird aufgerufen, erfolgreich
beendet. Dann kommen die WindowState-Ereignisse: auf, zu
Vom Timing her sieht das so aus (vorne der GetTickCount()):
Restore enter
Restore leave
3478183 ws: wsNormal prev: wsMinimized
3478184 ws: wsMinimized prev: wsNormal
3478191 ws: wsNormal prev: wsMinimized
WTF??? Das Timing hängt ein bißchen vom Rechner ab. Auf dem alten Laptop
sind es durchaus mal >10ms zwischen 1. und 3. Ereignis.
Habe spasseshalber eine Abfrage in OnWindowStateChange gemacht, daß er
erst wieder 100ms nach Restore auf Minimize reagiert. Das funktioniert,
aber schön ist anders.
Kennt jemand das Phänomen? Kann mir jemand auf die Sprünge helfen, was
ich falsch mache? So kompliziert kann das doch nicht sein?
VG Gartenbahner
Lazarus Version 1.6
FPC Version 3.0.0
aktuell nur auf PC mit Linux Mint, raspberry mit OSMC bzw Debian kommt
noch
[gelöst] TForm: Mehrfaches OnWindowStateChange
-
- Beiträge: 2
- Registriert: Do 17. Sep 2020, 13:15
- OS, Lazarus, FPC: Linux (L 1.6 FPC 3.0.0)
- CPU-Target: x86-64, ARM-HF
- Wohnort: Pfalz
[gelöst] TForm: Mehrfaches OnWindowStateChange
Zuletzt geändert von gartenbahner78 am Do 17. Sep 2020, 15:40, insgesamt 1-mal geändert.
Etwas nicht zu können ist kein Grund, es nicht zu tun
- Winni
- Beiträge: 1577
- Registriert: Mo 2. Mär 2009, 16:45
- OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
- CPU-Target: 64Bit
- Wohnort: Fast Dänemark
Re: TForm: Mehrfaches OnWindowStateChange(
Hi!
Ich hab spontan keine Lösung, aber zwei Anmerkungen:
* Wann immer man die Größe der Form ändert, so wird resize mindestens zweimal ausgeführt. In wie weit sich das auf die Änderung des WindowState auswirkt, weiss ich nicht. Das hat mich schon mal crazygemacht. Zur Erheiterung: Lass mal bei Form.OnResize einen Counter mitlaufen. Beim Programmstart wird - glaub ich - onResize 4 Mal ausgelöst.
* Da es hier letztendlich um die Zustands-Änderung von wsMinimized zu einem sichtbaren Zustand geht, kann man mit visible arbeiten. Wenn das Programm im Taskbar verschwindenn soll, kann man sofort visible auf false stellen. Dann wird auch deutlich weniger "hinter der Bühne" geändert. Und umgekehrt sollte man erst im allerletzten Moment show auslösen. Dann gibt's weniger Gezappel.
Winni
Ich hab spontan keine Lösung, aber zwei Anmerkungen:
* Wann immer man die Größe der Form ändert, so wird resize mindestens zweimal ausgeführt. In wie weit sich das auf die Änderung des WindowState auswirkt, weiss ich nicht. Das hat mich schon mal crazygemacht. Zur Erheiterung: Lass mal bei Form.OnResize einen Counter mitlaufen. Beim Programmstart wird - glaub ich - onResize 4 Mal ausgelöst.
* Da es hier letztendlich um die Zustands-Änderung von wsMinimized zu einem sichtbaren Zustand geht, kann man mit visible arbeiten. Wenn das Programm im Taskbar verschwindenn soll, kann man sofort visible auf false stellen. Dann wird auch deutlich weniger "hinter der Bühne" geändert. Und umgekehrt sollte man erst im allerletzten Moment show auslösen. Dann gibt's weniger Gezappel.
Winni
-
- Beiträge: 2
- Registriert: Do 17. Sep 2020, 13:15
- OS, Lazarus, FPC: Linux (L 1.6 FPC 3.0.0)
- CPU-Target: x86-64, ARM-HF
- Wohnort: Pfalz
Re: TForm: Mehrfaches OnWindowStateChange()
Hi Winni,
danke für die Antwort! Hat mir tatsächlich weitergeholfen
Die Lösung sieht jetzt so aus
OnMinimize:
self.visible:=false;
self.WindowState:=wsNormal;
OnRestore:
self.Visible:=true;
Und siehe da: Das Ergebnis entspricht dem Erwartungswert
Restore enter
Restore leave
20755515 ws: wsNormal prev: wsMinimized
Hätte ich eigentlich auch selbst drauf kommen können
Die Hölle beginnt erst, wenn man Show() und Hide() bemüht. Ursprünglich dachte ich mal (zumindest in den Sourcen von Delphi5 mal dunkel erinnernd gesehen?), daß visible nur das Property um die beiden ist, aber ist es anscheinend nicht...
Nochmal vielen Dank für die Hilfe!
VG Gartenbahner
danke für die Antwort! Hat mir tatsächlich weitergeholfen
Die Lösung sieht jetzt so aus
OnMinimize:
self.visible:=false;
self.WindowState:=wsNormal;
OnRestore:
self.Visible:=true;
Und siehe da: Das Ergebnis entspricht dem Erwartungswert
Restore enter
Restore leave
20755515 ws: wsNormal prev: wsMinimized
Hätte ich eigentlich auch selbst drauf kommen können
Die Hölle beginnt erst, wenn man Show() und Hide() bemüht. Ursprünglich dachte ich mal (zumindest in den Sourcen von Delphi5 mal dunkel erinnernd gesehen?), daß visible nur das Property um die beiden ist, aber ist es anscheinend nicht...
Nochmal vielen Dank für die Hilfe!
VG Gartenbahner
Etwas nicht zu können ist kein Grund, es nicht zu tun
Re: [gelöst] TForm: Mehrfaches OnWindowStateChange
Warum machst du das so kompliziert? Ich meine, der jeweilige Zweizeilergartenbahner78 hat geschrieben: ↑Do 17. Sep 2020, 13:22Wenn das Fenster (bei mir einziges Fenster des Programms, keine Children) minimiert wird, dann soll es ausgeblendet werden und ein TrayIcon erscheinen. Wenn ich auf das TrayIcon klicke, dann soll das Fenster wieder erscheinen.
Code: Alles auswählen
procedure TForm1.Button1Click(Sender: TObject);
begin
Hide;
TrayIcon1.Show;
end;
procedure TForm1.TrayIcon1Click(Sender: TObject);
begin
TrayIcon1.Hide;
Show;
end;