Application.ProcessMessages ohne Wirkung

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
sporex
Beiträge: 8
Registriert: Sa 5. Jan 2013, 15:28

Application.ProcessMessages ohne Wirkung

Beitrag von sporex »

Hallo Freunde,
hier eine simple Frage von jemandem der seine ersten Schritte mit Lazarus versucht :
warum funktioniert der unten stehende code nicht wie er sollte, also dass bei jedem 1 Mio n'sten Schritt der Schleife der Wert von i als Label angezeigt wird.
Stattdessen wird Form1 erst geöffnet wenn die Schleife komplett durchlaufen ist, und es wird nur der letzte Wert von i als Label1 angezeigt.
(Lazarus v.1.0.2; FPC 2.6.0; SVN Ver.39019; CPU i386 win32)

Vielen Dank im Voraus
Gruss R.N.

Code: Alles auswählen

 
type
 
  { TForm1 }
 
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject); //wird im objectinspector durch oncreate aufgerufen
    procedure main;
  private
    { private declarations }
  public
 
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.lfm}
 
procedure TForm1.FormCreate(Sender: TObject);
begin
  main;
end;
 
procedure TForm1.main;
 var i,j:longint;
begin
 
   for i:=0 to 1000000000 do begin
       if (i mod 1000000)=0 then begin
           Label1.caption:=IntToStr(i);
           Application.ProcessMessages;
       end;
   end;
end;
 
end.   
 
Zuletzt geändert von Lori am Sa 5. Jan 2013, 19:26, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Re: Application.ProcessMessages ohne Wirkung

Beitrag von theo »

OnCreate ist zu früh, da ist das Formular noch nicht sichtbar.
OnShow wäre geeigneter.

sporex
Beiträge: 8
Registriert: Sa 5. Jan 2013, 15:28

Re: Application.ProcessMessages ohne Wirkung

Beitrag von sporex »

theo hat geschrieben:OnCreate ist zu früh, da ist das Formular noch nicht sichtbar.
OnShow wäre geeigneter.
Danke für den Hinweis.
OnShow hat zwar nichts gebracht, aber wenn ich OnActivate verwende funktioniert es.

Aber bitte noch eine grundsätzliche Frage : ist der Befehl Application.ProcessMessages wirklich eine "saubere" Lösung?
Ich habe irgendwo gelesen dass es dabei zu unerwünschten Nebeneffekten kommen kann.
Irgendwo anders habe ich gelesen, dass man soetwas über "Threads" programmiert.
Leider habe ich davon keine Ahnung, da ich bisher nur mit FPC console applications gearbeitet habe.
Gibt es dafür eine Seite die das Thema für Einsteiger gut erklärt?

Gruss R.N.

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Re: Application.ProcessMessages ohne Wirkung

Beitrag von theo »

sporex hat geschrieben: Aber bitte noch eine grundsätzliche Frage : ist der Befehl Application.ProcessMessages wirklich eine "saubere" Lösung?
Ich habe irgendwo gelesen dass es dabei zu unerwünschten Nebeneffekten kommen kann.
Irgendwo anders habe ich gelesen, dass man soetwas über "Threads" programmiert.
Leider habe ich davon keine Ahnung, da ich bisher nur mit FPC console applications gearbeitet habe.
Gibt es dafür eine Seite die das Thema für Einsteiger gut erklärt?
Für diesen Fall ist es schon richtig.

Zu Threads gibt es hier was: http://wiki.freepascal.org/Multithreade ... utorial/de

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Application.ProcessMessages ohne Wirkung

Beitrag von Heinrich Wolf »

Vorsicht!

OnShow und OnActivate werden vielfach zur Laufzeit aufgerufen. Wenn Dein Code nur einmal aufgerufen werden soll, kannst Du es so machen:

Code: Alles auswählen

type
  TForm1 = class(TForm);
    ...
  private
    FirstActivate : Boolean;
  end;
 
procedure TForm1.FormCreate(Sender : TObject);
  begin
     FirstActivate := True;
  end;
 
procedure TForm1.FormActivate(Sender : TObject);
  begin
     if FirstActivate then
       begin
          FirstActivate := False;
          // Hier Dein Code
       end;
  end;
ProcessMessages verwende ich auch gerne (lieber als Threads). Du musst aufpassen, dass Du unerwünschte Events nicht erneut aufrufst. Zu diesem Zweck mache ich mir immer eine EnableAll(Enabled : Boolean) Methode, mit der ich z.B. alle Buttons, Edits usw. disable, solange die zeitraubende Prozedur läuft.

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Re: Application.ProcessMessages ohne Wirkung

Beitrag von theo »

Heinrich Wolf hat geschrieben:Vorsicht!
OnShow und OnActivate werden vielfach zur Laufzeit aufgerufen.
Naja, OnShow, wird nur aufgerufen, wenn das Formular sichtbar (visible) wird. Also bei einem Hauptformular praktisch nur einmal, wenn man keine Trayicon Tricks drin hat.
Das kann man schon problemlos und ohne Panik verwenden.

sporex
Beiträge: 8
Registriert: Sa 5. Jan 2013, 15:28

Re: Application.ProcessMessages ohne Wirkung

Beitrag von sporex »

Vielen Dank nochmals an alle.
Wenn ich das Verhindern von OnActivate zur Laufzeit richtig verstanden habe müsste es so aussehen wie unten:


Code: Alles auswählen

 
type
  TForm1 = class(TForm);
    ...
  private
    FirstActivate : Boolean;
  end;
 
procedure TForm1.FormCreate(Sender : TObject);  // wird durch Einstellung im Object Inspector beim ersten OnActivate aufgerufen
  begin
     FirstActivate := True;
  end;
 
procedure TForm1.FormActivate(Sender : TObject);
  begin
     if FirstActivate then
       begin
          FirstActivate := False;
          main;                                  // Aufruf der prozedur main (indirekt über FormCreate); weitere Aufrufe zur LZ werden verhindert weil FirstActivate dann False
       end;
  end;
Zuletzt geändert von Lori am Sa 5. Jan 2013, 21:39, insgesamt 1-mal geändert.
Grund: richtiger Highlighter

Heinrich Wolf
Beiträge: 323
Registriert: Di 12. Apr 2011, 13:21
OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
CPU-Target: 1core 1,8GHz 32Bit
Wohnort: Fürth
Kontaktdaten:

Re: Application.ProcessMessages ohne Wirkung

Beitrag von Heinrich Wolf »

Code: Alles auswählen

 
type
  TForm1 = class(TForm);
    ...
  private
    FirstActivate : Boolean;
  end;
 
procedure TForm1.FormCreate(Sender : TObject);  // Kommentar geändert: Wird im Object Inspector zugewiesen und OnCreate zur Initialisierung der Variable aufgerufen
  begin
     FirstActivate := True;
  end;
 
procedure TForm1.FormActivate(Sender : TObject);
  begin
     if FirstActivate then
       begin
          FirstActivate := False;
          main;                                  // Kommentar geändert: Aufruf der prozedur main (über FormActivate); weitere Aufrufe zur LZ werden verhindert weil FirstActivate dann False
       end;
  end;

sporex
Beiträge: 8
Registriert: Sa 5. Jan 2013, 15:28

Re: Application.ProcessMessages ohne Wirkung

Beitrag von sporex »

OK, verstanden.

Vielen Dank.

Gruss R.N

Antworten