AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Vermeiden von Application.Processmessages
Thema durchsuchen
Ansicht
Themen-Optionen

Vermeiden von Application.Processmessages

Ein Thema von Mavarik · begonnen am 20. Mai 2015 · letzter Beitrag vom 20. Mai 2015
Antwort Antwort
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#1

Vermeiden von Application.Processmessages

  Alt 20. Mai 2015, 11:02
Kommt jedes mal wenn die Form/App den Focus erhält... (Windows)
Create nur 1x!

Doch nochmal zum Thread Thema

Beispiel alt:

Delphi-Quellcode:
procedure TMainForm.FormCreate(Sender: TObject);
begin
  LeftPanel.Width := 100;
  RightPanel.Width := 100;
  // Center Panel is align Client... Aber wie groß jetzt
  Application.Processmessages;
  Width_für_neue_Berechnung := CenterPanel.Width;
  Berechne_Element_auf_CenterPanel(Width_für_neue_Berechnung);
  ...
end;
Beispiel neu:

Delphi-Quellcode:
procedure TMainForm.FormCreate(Sender: TObject);
begin
  LeftPanel.Width := 100;
  RightPanel.Width := 100;
  TThread.Queue(NIL,Procedure ()
                      begin
                        Width_für_neue_Berechnung := CenterPanel.Width;
                        Berechne_Element_auf_CenterPanel(Width_für_neue_Berechnung);
                      end);

  // In der Hoffnung hier den Wert nicht auch zu brauchen...
end;
Mavarik

Geändert von Mavarik (20. Mai 2015 um 11:05 Uhr)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 11:12
Kommt jedes mal wenn die Form/App den Focus erhält... (Windows)
Create nur 1x!
Ja. Zugegeben, man muss man sich einmal merken ob das OnActivate nun schon mal stattgefunden hat oder nicht:

Delphi-Quellcode:
type
   TBaseForm = class(TForm)
      procedure FormActivate(Sender: TObject);
      private var
         firstActivateHappened: Boolean;
      public
         procedure initGUI(); virtual;
   end;

procedure TBaseForm.initGUI();
begin
   // Empty
end;

procedure TBaseForm.FormActivate(Sender: TObject);
begin
   if (not firstActivateHappened) then begin
      initGUI();
      firstActivateHappened := True;
   end;
   inherited;
end;
Das sind zwar zwei Zeilen mehr als es im OnCreate zu machen, aber eine Boolean-Variable ist im Vergleich zu einem TThread.Queue(..) oder Application.ProcessMessages() so herrlich unspektakulär

Du hättest nun einfach
Delphi-Quellcode:
procedure TMainForm.initGUI();
begin
   inherited;   
   Berechne_Element_auf_CenterPanel(CenterPanel.Width);
end;
Genau für Dinge wie "Wie groß ist das Element nun?" nehme ich immer "meine" OnActivate -Lösung und war damit eigentlich immer glücklich.
  Mit Zitat antworten Zitat
Benutzerbild von baumina
baumina

Registriert seit: 5. Mai 2008
Ort: Oberschwaben
1.275 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 11:14
Ich hab sowas in OnShow ebenfalls mit einer Variable FirstShow.
Hinter dir gehts abwärts und vor dir steil bergauf ! (Wolfgang Ambros)
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.176 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 11:17
Ja, das wäre ja genau das gleiche. Ich meine, ich hatte irgendeinen Grund, OnActivate statt OnShow zu nehmen. Wenn ich nicht falsch liege, kommt erst OnShow , dann OnActivate .
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 11:23
Hier mal ein Best Practice und DontDo Beispiel
Delphi-Quellcode:
unit Form.Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,
  FMX.Controls.Presentation, FMX.StdCtrls;

type
  TForm1 = class( TForm )
    ToolBar1: TToolBar;
    Text1: TText;
    Label1: TLabel;
    procedure FormCreate( Sender: TObject );
  private
    procedure MeasureTextControl( AText: TText );
    procedure QueueMeasureTextControl( AText: TText );
    procedure DontDoMeasureTextControl( AText: TText );
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

{ TForm1 }

procedure TForm1.FormCreate( Sender: TObject );
begin
  Text1.Align := TAlignLayout.Client;

  // funktioniert
  // MeasureTextControl( Text1 );

  // funktioniert - Best Practice
  QueueMeasureTextControl( Text1 );

  // Fehlerhafte Darstellung
  // DontDoMeasureTextControl( Text1 );
end;

procedure TForm1.DontDoMeasureTextControl( AText: TText );
begin
  Application.ProcessMessages;
  MeasureTextControl( AText );
end;

procedure TForm1.MeasureTextControl( AText: TText );
begin
  Label1.Text := AText.Width.ToString;
end;

procedure TForm1.QueueMeasureTextControl( AText: TText );
begin
  TThread.Queue( nil,
    procedure
    begin
      MeasureTextControl( AText );
    end );
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 11:48
TThread.Queue kannst du dir an der Stelle sparen, da es sofort ausgeführt wird.
(zumindestens in Windows, aber vermutlich auch im NextGen usw.)

http://www.delphipraxis.net/179193-t...der-queue.html
$2B or not $2B

Geändert von himitsu (20. Mai 2015 um 11:50 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.144 Beiträge
 
Delphi 10.3 Rio
 
#7

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 12:52
TThread.Queue kannst du dir an der Stelle sparen, da es sofort ausgeführt wird.
(zumindestens in Windows, aber vermutlich auch im NextGen usw.)

http://www.delphipraxis.net/179193-t...der-queue.html
Das kommt davon, wenn man ungetesten code postet...

Hatte ich inzwischen schon geändert... in einen OnIdle Handler...
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 13:01
Ja, ja ...

Dann ebend so ... menno

Delphi-Quellcode:
procedure TForm1.QueueMeasureTextControl( AText: TText );
begin
  TThread.ExecLater<TText>( MeasureTextControl, AText );
end;
Gut, dafür braucht man einen ThreadHelper
Delphi-Quellcode:
unit ThreadHelper;

interface

uses
  System.Classes,
  System.SysUtils;

type
  TThreadHelper = class helper for TThread
    class procedure ExecLater( AProc: TProc ); overload;
    class procedure ExecLater<T>( AProc: TProc<T>; AArg: T ); overload;
    class procedure ExecLater<T1, T2>( AProc: TProc<T1, T2>; AArg1: T1; AArg2: T2 ); overload;
    class procedure ExecLater<T1, T2, T3>( AProc: TProc<T1, T2, T3>; AArg1: T1; AArg2: T2; AArg3: T3 ); overload;
    class procedure ExecLater<T1, T2, T3, T4>( AProc: TProc<T1, T2, T3, T4>; AArg1: T1; AArg2: T2; AArg3: T3; AArg4: T4 ); overload;
  end;

implementation

{ TThreadHelper }

class procedure TThreadHelper.ExecLater( AProc: TProc );
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Current.Synchronize(
        procedure
        begin
          AProc( );
        end );
    end ).Start( );
end;

class procedure TThreadHelper.ExecLater<T1, T2, T3, T4>( AProc: TProc<T1, T2, T3, T4>; AArg1: T1; AArg2: T2; AArg3: T3; AArg4: T4 );
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Current.Synchronize(
        procedure
        begin
          AProc( AArg1, AArg2, AArg3, AArg4 );
        end );
    end ).Start( );
end;

class procedure TThreadHelper.ExecLater<T1, T2, T3>( AProc: TProc<T1, T2, T3>; AArg1: T1; AArg2: T2; AArg3: T3 );
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Current.Synchronize(
        procedure
        begin
          AProc( AArg1, AArg2, AArg3 );
        end );
    end ).Start( );
end;

class procedure TThreadHelper.ExecLater<T1, T2>( AProc: TProc<T1, T2>; AArg1: T1; AArg2: T2 );
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Current.Synchronize(
        procedure
        begin
          AProc( AArg1, AArg2 );
        end );
    end ).Start( );
end;

class procedure TThreadHelper.ExecLater<T>( AProc: TProc<T>; AArg: T );
begin
  TThread.CreateAnonymousThread(
    procedure
    begin
      TThread.Current.Synchronize(
        procedure
        begin
          AProc( AArg );
        end );
    end ).Start( );
end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Daniel
(Co-Admin)

Registriert seit: 30. Mai 2002
Ort: Hamburg
13.920 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Vermeiden von Application.Processmessages

  Alt 20. Mai 2015, 13:12
Ich habe mir erlaubt, den Themen-Titel anzupassen.
Vermutlich geht es eher um "vermeiden" als "vernichten".
Daniel R. Wolf
mit Grüßen aus Hamburg
  Mit Zitat antworten Zitat
Thomas_K

Registriert seit: 16. Apr 2006
71 Beiträge
 
Delphi XE8 Professional
 
#10

AW: Vernichten von Application.Processmessages

  Alt 20. Mai 2015, 14:19

Ja. Zugegeben, man muss man sich einmal merken ob das OnActivate nun schon mal stattgefunden hat oder nicht:

Delphi-Quellcode:
type
   TBaseForm = class(TForm)
      procedure FormActivate(Sender: TObject);
      private var
         firstActivateHappened: Boolean;
      public
         procedure initGUI(); virtual;
   end;

procedure TBaseForm.initGUI();
begin
   // Empty
end;

procedure TBaseForm.FormActivate(Sender: TObject);
begin
   if (not firstActivateHappened) then begin
      initGUI();
      firstActivateHappened := True;
   end;
   inherited;
end;
Die Hilfsvariablensteuerung kann man sich sparen, wenn sich die Ereignis- Routine selbst vom Objekt/Instanz abkoppelt.

Delphi-Quellcode:
type
  TBaseForm = class(TForm)
    procedure FormActivate(Sender: TObject);
  public
    procedure initGUI(); virtual;
  end;

procedure TBaseForm.initGUI();
begin
   // Empty
end;

procedure TBaseForm.FormActivate(Sender: TObject);
begin
   OnActivate = nil;
   initGUI();
   firstActivateHappened := True;
   inherited;
end;
Die selbe Funktionalität wie oben, nur mit weniger Code.
  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 06:08 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