Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   OnIdle wird immer wieder ausgeführt (https://www.delphipraxis.net/48784-onidle-wird-immer-wieder-ausgefuehrt.html)

RavenIV 30. Jun 2005 10:00


OnIdle wird immer wieder ausgeführt
 
Hallo

ich möchte, dass mein MainForm bei dem Ereignis Application.OnIdle ins SystemTray minimiert wird.
Dazu benutze ich CoolTrayIcon.

Um die Sache zu testen, lasse ich in myIdleHandler einen TTimer loslaufen und bei Ablauf des Timer eine Application.MessageBox anzeigen.
Jedoch kommt diese MessageBox immer wieder.

Wie kann ich es nun anstellen, dass die MainForm das Ereignis OnIdle nur einmal bekommt und sich dann minimiert ins SystemTray (mit CoolTrayIcon)?

gruessle

Steve 30. Jun 2005 10:03

Re: OnIdle wird immer wieder ausgeführt
 
Hi,

eine Möglichkeit sollte z.B. diese sein:
Delphi-Quellcode:
//...in myIdleHandler():
begin
  Application.OnIdle := NIL;
  // Dein Code
end;

Gruß
Stephan :dance:

Stefan Dieler 30. Jun 2005 10:05

Re: OnIdle wird immer wieder ausgeführt
 
Hallo RavenIV,

wenn ich dich richtig verstanden habe, dann schalte doch beim Minimieren in die Tray-Leiste das OnIdle-Event ab, bzw. frag innerhalb dieses Events ab, ob die Anwendung minimiert ist, oder nicht.
Wenn die Anwendung maximiert wird, dann kannst du das Event ja wieder anschalten bzw. abarbeiten.

RavenIV 30. Jun 2005 10:40

Re: OnIdle wird immer wieder ausgeführt
 
nun habe ich das Problem, dass das Form auch nach der Timer-Zeit minimiert wird, obwohl ich dort Eingaben gemacht habe.

Eigentlich möchte ich erreichen, dass das Form nur minimiert wird, wenn der benutzer n Sekunden lang keine Eingabe macht oder keinen Button drückt oder sonst irgendwas (verschieben, Grösse ändern,...) mit dem Fenster macht.
Bibt's dazu denn nicht irgendwas fertiges oder wenigstens einen Schubser in die richtige Richtung?

gruessle

Stefan Dieler 30. Jun 2005 10:46

Re: OnIdle wird immer wieder ausgeführt
 
Hallo,

vielleicht funktioniert es, wenn du im Formular KeyPreview aus True setzt und dann bei OnKeyPress nach Tastendruck deinen Timer neu starten lässt. Bei OnMouseMove dann das gleiche.
Weiß aber nicht, wie sich das auf die Performance auswirkt.

shmia 30. Jun 2005 11:09

Re: OnIdle wird immer wieder ausgeführt
 
Zitat:

Zitat von RavenIV
Eigentlich möchte ich erreichen, dass das Form nur minimiert wird, wenn der benutzer n Sekunden lang keine Eingabe macht oder keinen Button drückt oder sonst irgendwas (verschieben, Grösse ändern,...) mit dem Fenster macht.
Bibt's dazu denn nicht irgendwas fertiges oder wenigstens einen Schubser in die richtige Richtung?

Alle Windows-Messages, die dein Programm erhält, können über Application.OnMessage abgefangen werden.
Nur bestimmte Messages sind für dich ein Zeichen, dass der User noch mit deinem Prog arbeitet. (Mausbewegungen gehören z.B. nicht dazu)
Du merkst dir einfach den Zeitpunkt der letzten Message.
Delphi-Quellcode:
var
   lastMsgTime : DWORD;
procedure TFormMain.HandleOnMessage(var Msg: TMsg; var Handled: Boolean);
begin
   case Msg.message of
      WM_MOUSEWHEEL:
      WM_CHAR:
         lastMsgTime := Msg.time;
   end;
end;
In OnIdle kannst du dann überprüfen, ob die letzte relevante Message mehr als 10s in der
Vergangenheit liegt und dann deine Aktion starten.

Sidorion 4. Jul 2005 13:36

Re: OnIdle wird immer wieder ausgeführt
 
Also:
1. OnIdle Event der Applikation mit nem Handler versehen.
2. Im OnIdle Handler die variable Done auf true setzen, das verhindert, daß OnIdle immer wieder aufgerufen wird.
3. im OnIdle deinen Timer neu starten (Timer.Enabled:=False; Timer.Enabled:=True) .. dann fängt er neu an zu zählen.
4. Im OnTimer event des Timers dann die MainForm minimieren und den Timer disablen.

Jetzt sollte eigentlich nach jeder Aktion des Nutzers die OnIdle gerufen werden und nur wenn er zwischendurch nix macht wird die OnIdle dann nicht mehr gerufen (weil immer nur einmal gerufen wird durch das Done:=True). Wenn jetzt dein Timer losschlägt wird die Form minimiert, aber nur einmal, da er danach ausgeschaltet ist. Durch das reinitialisieren des Timers im OnIdle wird verhindert, daß er ständig losschlägt, sondern nur, wenn OnIdle länger als das eingestellte Intervall nicht aufgerufen wurde.

RavenIV 4. Jul 2005 14:52

Re: OnIdle wird immer wieder ausgeführt
 
@Sidorion:
danke für den Tip, aber der OnIdle wird trotz Done := True immerwieder aufgerufen.

hier ein Auszug aus meinen Sourcen:
Delphi-Quellcode:
procedure TFoTrayIcon.FormCreate(Sender: TObject);
begin
  Application.OnIdle := FoTrayIcon.MyIdleHandler;
  ...
  ...
end;

procedure TFoTrayIcon.MyIdleHandler(Sender: TObject; var Done: Boolean);
begin
  Done := True;
  TiIdleTimer.Enabled := False;
  TiIdleTimer.Enabled := True;
end;

procedure TFoTrayIcon.TiIdleTimerTimer(Sender: TObject);
begin
  FoTrayIcon.Hide;
  TiIdleTimer.Enabled := False;
end;
wo liegt mein Denkfehler?

Sidorion 4. Jul 2005 15:22

Re: OnIdle wird immer wieder ausgeführt
 
Das ist putzig, weil OnIdle eigentlich immer dann aufgerufen wird, wenn die Applikation idle geht, d.h. immer wenn ein Event fertig abgearbeitet wurde. Hast du eventuell noch andere timer laufen oder schickst du von aussen Nachrichten? Oder hast du evtl in der OnIdle procedure einen unterbrechungspunkt? .. daran kanns auch liegen, weil die Applikation ja durch das Unterbrechen an dieser Stelle den Fokus verliert und anschließend wiederkriegt, was natürlich zu einem neuen Aufruf von OnIdle führt.

RavenIV 4. Jul 2005 15:30

Re: OnIdle wird immer wieder ausgeführt
 
Zitat:

Zitat von Sidorion
Oder hast du evtl in der OnIdle procedure einen unterbrechungspunkt? .. daran kanns auch liegen, weil die Applikation ja durch das Unterbrechen an dieser Stelle den Fokus verliert und anschließend wiederkriegt, was natürlich zu einem neuen Aufruf von OnIdle führt.

jupp, zum testen hab ich da einen breakpoint gesetzt.

und wenn ich im OnTimer eine MsgBox anzeigen lasse, bekomme ich aus diesem Grund auch immer den Event?
=> MsgBox bekommt den Fokus, klick auf MsgBox->OK, Applikation bekommt wieder den Fokus, dann wieder Idle-Event?

gruessle

Sidorion 4. Jul 2005 15:40

Re: OnIdle wird immer wieder ausgeführt
 
Yupp. Aber in dem Fall nicht, weil die Applikation den Fokus kriegt, sondern weil sie irgendwann mit der Abarbeitung des Klicks auf den OK-Button fertig ist. Aber natürlich mit dem selben Ergebnis.

RavenIV 4. Jul 2005 15:49

Re: OnIdle wird immer wieder ausgeführt
 
Zitat:

Zitat von Sidorion
Yupp. Aber in dem Fall nicht, weil die Applikation den Fokus kriegt, sondern weil sie irgendwann mit der Abarbeitung des Klicks auf den OK-Button fertig ist. Aber natürlich mit dem selben Ergebnis.

OK, hab ich verstanden.
Danke.

shmia 4. Jul 2005 16:13

Re: OnIdle wird immer wieder ausgeführt
 
Ich denke, du kommst mit dem OnIdle Event auf keinen grünen Zweig.
Mit dem Event OnMessage (wie oben vorgeschlagen) kannst du alles kontrollieren:
Delphi-Quellcode:
var
   lastMsgTime : DWORD;

procedure TForm1.HandleOnMessage(var Msg: TMsg; var Handled: Boolean);
begin
   case Msg.message of
      WM_ACTIVATE,
      WM_ACTIVATEAPP,
      WM_CREATE,
      WM_SETFOCUS,
      WM_MOUSEWHEEL,
      WM_CHAR,
      WM_SYSCHAR,
      WM_RBUTTONDOWN,
      WM_LBUTTONDOWN,
      WM_MBUTTONDOWN,
      WM_MOVE,
      WM_MOVING:
         lastMsgTime := Msg.time;
   end;
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
   Application.OnMessage := HandleOnMessage;
   lastMsgTime := GetTickCount;
end;

// Timer feuert alle 500ms
procedure TForm1.Timer1Timer(Sender: TObject);
var
   x : DWORD;
   diff : DWORD;
begin
   x := GetTickCount;
   diff := x - lastMsgTime;

   if diff > 10000 then // > 10 Sekunden
      Caption := 'ich schlafe jetzt in der TNA'
   else
      caption := IntToStr(diff)+ 'ms seit letzter Message';
end;

RavenIV 4. Jul 2005 19:36

Re: OnIdle wird immer wieder ausgeführt
 
das "HandleOnMessage" funktioniert zu meiner Zufriedenheit.

kann es jedoch sein, dass die Message WM_MOVE nicht zu mir ins Programm kommt?
ich kann das Fenster auf dem Bildschirm rumschieben, wie ich will, die Zeit läuft aber weiter und irgendwas ist das Fenster in der TNA.

gruessle

shmia 5. Jul 2005 08:38

Re: OnIdle wird immer wieder ausgeführt
 
Zitat:

Zitat von RavenIV
kann es jedoch sein, dass die Message WM_MOVE nicht zu mir ins Programm kommt?
ich kann das Fenster auf dem Bildschirm rumschieben, wie ich will, die Zeit läuft aber weiter und irgendwas ist das Fenster in der TNA.

Das ist mir auch schon aufgefallen, dass WM_MOVE nicht ankommt.
Du kannst ja mal mit WM_WINDOWPOSCHANGED und/oder WM_WINDOWPOSCHANGING herumspielen.
WM_SIZE gehört auch noch in die Liste.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:38 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz