Delphi-PRAXiS
Seite 1 von 3  1 23   

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/)
-   -   .Controls und .Components nicht als Auflistung nutzbar? (https://www.delphipraxis.net/210560-controls-und-components-nicht-als-auflistung-nutzbar.html)

freejay 11. Mai 2022 12:46

.Controls und .Components nicht als Auflistung nutzbar?
 
Hallo zusammen,

kann es sein, dass man das Folgende immer noch nicht machen kann:

Delphi-Quellcode:
for MyControl in Panel1.Controls do


Muss man immer noch schreiben

Delphi-Quellcode:
for i := 0 to Panel1.ControlCount - 1 do


oder mache ich da bloß was falsch?

Danke im voraus!

Freejay

Uwe Raabe 11. Mai 2022 13:54

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Das ist immer noch so und einfach der Tatsache geschuldet, dass Controls ein Array-Property und eben kein Array ist.

Es gibt aber Abhilfe - und die ist sogar noch besser. Mit dem Code weiter unten kann man nämlich Folgendes schreiben:
Delphi-Quellcode:
  for var ctrl in ControlsOf<TButton> do
    ctrl.Caption := 'Hello World';
Delphi-Quellcode:
type
  TWinControlHelper = class helper for TWinControl
  type
    TControlEnumerator<T: TControl> = class
    private
      FIndex: Integer;
      FWinControl: TWinControl;
      function GetCurrent: T;
    public
      constructor Create(AWinControl: TWinControl);
      function MoveNext: Boolean;
      property Current: T read GetCurrent;
    end;

    IControls<T: TControl> = interface
      function GetEnumerator: TControlEnumerator<T>;
    end;

    TControls<T: TControl> = class(TInterfacedObject, IControls<T>)
    private
      FWinControl: TWinControl;
    public
      constructor Create(AWinControl: TWinControl);
      function GetEnumerator: TControlEnumerator<T>;
    end;
  public
    function ControlsOf<T: TControl>: IControls<T>;
  end;

{ TWinControlHelper }

function TWinControlHelper.ControlsOf<T>: IControls<T>;
begin
  Result := TControls<T>.Create(Self);
end;

{ TWinControlHelper.TControls<T> }

constructor TWinControlHelper.TControls<T>.Create(AWinControl: TWinControl);
begin
  inherited Create;
  FWinControl := AWinControl;
end;

function TWinControlHelper.TControls<T>.GetEnumerator: TControlEnumerator<T>;
begin
  Result := TControlEnumerator<T>.Create(FWinControl);
end;

constructor TWinControlHelper.TControlEnumerator<T>.Create(AWinControl: TWinControl);
begin
  inherited Create;
  FWinControl := AWinControl;
  FIndex := -1;
end;

function TWinControlHelper.TControlEnumerator<T>.GetCurrent: T;
begin
  Result := FWinControl.Controls[FIndex] as T;
end;

function TWinControlHelper.TControlEnumerator<T>.MoveNext: Boolean;
begin
  repeat
    Inc(FIndex);
    if FIndex >= FWinControl.ControlCount then
      Exit(False);
    if FWinControl.Controls[FIndex] is T then
      Exit(True);
  until False;
end;

Uwe Raabe 11. Mai 2022 14:16

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Hier auch noch das Pendant für Components:
Delphi-Quellcode:
type
  TComponentHelper = class helper for TComponent
  type
    TComponentEnumerator<T: TComponent> = class
    private
      FIndex: Integer;
      FComponent: TComponent;
      function GetCurrent: T;
    public
      constructor Create(AComponent: TComponent);
      function MoveNext: Boolean;
      property Current: T read GetCurrent;
    end;

    IComponents<T: TComponent> = interface
      function GetEnumerator: TComponentEnumerator<T>;
    end;

    TComponents<T: TComponent> = class(TInterfacedObject, IComponents<T>)
    private
      FComponent: TComponent;
    public
      constructor Create(AComponent: TComponent);
      function GetEnumerator: TComponentEnumerator<T>;
    end;
  public
    function ComponentsOf<T: TComponent>: IComponents<T>;
  end;

{ TComponentHelper }

function TComponentHelper.ComponentsOf<T>: IComponents<T>;
begin
  Result := TComponents<T>.Create(Self);
end;

{ TComponentHelper.TComponents<T> }

constructor TComponentHelper.TComponents<T>.Create(AComponent: TComponent);
begin
  inherited Create;
  FComponent := AComponent;
end;

function TComponentHelper.TComponents<T>.GetEnumerator: TComponentEnumerator<T>;
begin
  Result := TComponentEnumerator<T>.Create(FComponent);
end;

constructor TComponentHelper.TComponentEnumerator<T>.Create(AComponent: TComponent);
begin
  inherited Create;
  FComponent := AComponent;
  FIndex := -1;
end;

function TComponentHelper.TComponentEnumerator<T>.GetCurrent: T;
begin
  Result := FComponent.Components[FIndex] as T;
end;

function TComponentHelper.TComponentEnumerator<T>.MoveNext: Boolean;
begin
  repeat
    Inc(FIndex);
    if FIndex >= FComponent.ComponentCount then
      Exit(False);
    if FComponent.Components[FIndex] is T then
      Exit(True);
  until False;
end;

Uwe Raabe 11. Mai 2022 14:23

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Interessanterweise gibt es bereits einen Enumerator für Components, allerdings nicht generisch:
Delphi-Quellcode:
  for var cmp in Self do
    if cmp is TButton then
      TButton(cmp).Caption := 'Hello World';

freejay 11. Mai 2022 15:45

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Vielen Dank!

Nicht falsch verstehen jetzt (ich bin sehr dankbar für die aufgezeigte Lösung), aber:

Das ist sicher besser als for i := 0 to ... aber es sieht wie eine Funktion aus, die man mit dem Control aufruft und das wirkt irgendwie "un-objektorientiert"...

Ich nehme an diese Helper sind (noch) nicht Bestandteil von Delphi?

Uwe Raabe 11. Mai 2022 16:04

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Zitat:

Zitat von freejay (Beitrag 1505711)
aber es sieht wie eine Funktion aus, die man mit dem Control aufruft und das wirkt irgendwie "un-objektorientiert"

Kannst du diese Aussage etwas präzisieren?
Was am Aufruf einer function eines Objekts ist denn un-objektorientiert? (Oder allgemeiner: Was bedeutet un-objektorientiert überhaupt?)
Würde diese function ein
Delphi-Quellcode:
TArray<TControl>
zurückgeben, was ja problemlos mit for-in iteriert werden kann, wäre das dann auch un-objektorientiert?
Immerhin wird sowas ja bereits an vielen Stellen in Delphi gemacht, z.B.
Delphi-Quellcode:
TStringList.ToStringArray
.

Zitat:

Zitat von freejay (Beitrag 1505711)
Ich nehme an diese Helper sind (noch) nicht Bestandteil von Delphi?

Nein, die sind von mir. Wären sie in Delphi drin, wären es vermutlich keine Helper, sondern die Funktionalität wäre direkt in TComponent bzw. TWinControl implementiert.

mkinzler 11. Mai 2022 16:06

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Zitat:

Das ist sicher besser als for i := 0 to ... aber es sieht wie eine Funktion aus, die man mit dem Control aufruft und das wirkt irgendwie "un-objektorientiert"...
Delphi-Quellcode:
for var ctrl in ControlsOf<TButton> do
    ctrl.Caption := 'Hello World';
Doch ist doch objektorientiert. Oder wie sollte es nach Deiner Meinung aussehen, wenn es objektorientiert wäre?

Uwe Raabe 11. Mai 2022 16:09

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Man sollte vielleicht erwähnen, dass das ControlsOf in diesem Fall ja das des Forms ist, in dessen Event-Handler es aufgerufen wird. Wollte man das auf ein Panel anwenden, um z.B. die Buttons auf diesem Panel zu verarbeiten, müsste man das so schreiben:
Delphi-Quellcode:
for var ctrl in Panel1.ControlsOf<TButton> do
  ctrl.Caption := 'Hello World';

Medium 11. Mai 2022 21:47

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1505712)
die Funktionalität wäre direkt in TComponent bzw. TWinControl implementiert.

Stellt sich die Frage: Wieso ist es das eigentlich nicht? Das ist doch ziemlich ein Paradebeispiel für solch ein Konstrukt. Bin ich auch schon kräftig drüber gestolpert, und war doch recht verwundert ob der Tatsachen.

himitsu 11. Mai 2022 21:57

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
für Components gibt es bereits einen Enumerator

Delphi-Quellcode:
for var C in IrgendeineTComponentInstanz do


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:14 Uhr.
Seite 1 von 3  1 23   

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