Delphi-PRAXiS
Seite 3 von 3     123

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)

Heimlich 25. Mai 2022 12:00

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

Zitat von Uwe Raabe (Beitrag 1505732)
Stefan Glienke hat gestern noch ein wenig Hand angelegt und ich möchte euch das Ergebnis nicht vorenthalten:

Zitat:

Zitat von Stevie
hab mal deinen control enumerator umgeschrieben, um jegliche allokationen zu vermeiden und alle methoden inlinen zu lassen

Delphi-Quellcode:
type
  TWinControlHelper = class helper for TWinControl
  type
    TControlEnumerator<T: TControl> = record
    private
      FIndex, FCount: Integer;
      FWinControl: TWinControl;
      FCurrent: T;
    public
      function MoveNext: Boolean; inline;
      property Current: T read FCurrent;
    end;

    TControls<T: TControl> = record
    private
      FWinControl: TWinControl;
    public
      function GetEnumerator: TControlEnumerator<T>; inline;
    end;
  public
    function ControlsOf<T: TControl>: TControls<T>; inline;
  end;

{ TWinControlHelper }

function TWinControlHelper.ControlsOf<T>: TControls<T>;
begin
  Result.FWinControl := Self;
end;

{ TWinControlHelper.TControls<T> }

function TWinControlHelper.TControls<T>.GetEnumerator: TControlEnumerator<T>;
begin
  Result.FIndex := 0;
  Result.FWinControl := FWinControl;
  Result.FCount := FWinControl.ControlCount;
end;

function TWinControlHelper.TControlEnumerator<T>.MoveNext: Boolean;
var
  LControl: TControl;
begin
  repeat
    if FIndex < FCount then
    begin
      LControl := FWinControl.Controls[FIndex];
      Inc(FIndex);
      if LControl.InheritsFrom(T) then
      begin
        FCurrent := T(LControl);
        Exit(True);
      end;
    end
    else
      Exit(False)
  until False;
end;


Wie sieht es denn bei folgender Konstellation aus?

Delphi-Quellcode:
for i := 0 to ComponentCount-1 do
if Components[i] is TButton then
  TButton(Components[i]).Caption := 'Hello World'
else
if Components[i] is TPageControl then
  TPageControl(Components[i]).ActivePageIndex := 0
else
if Components[i] is TEdit then
  TEdit(Components[i]).Font.Style := [fsBold];
Man bräuchte dann ja 3 Durchläufe, anstatt, wie im Beispiel zusehen, nur einen Durchlauf.

Uwe Raabe 25. Mai 2022 16:50

AW: .Controls und .Components nicht als Auflistung nutzbar?
 
Das ist dann halt eine andere Anforderung, für die man ja immer noch den Standard-Enumerator verwenden kann:
Delphi-Quellcode:
for var cmp in Self do begin
  if cmp is TButton then
    TButton(cmp).Caption := 'Hello World'
  else if cmp is TPageControl then
    TPageControl(cmp).ActivePageIndex := 0
  else if cmp is TEdit then
    TEdit(cmp).Font.Style := [fsBold];
end;
Eigentlich ist das aber ein Anwendungsfall für das Visitor Pattern:
Delphi-Quellcode:
type
  TMyVisitor = class(TVisitor) { Source für TVisitor siehe Link }
  public
    procedure VisitButton(Instance: TButton);
    procedure VisitPageControl(Instance: TPageControl);
    procedure VisitEdit(Instance: TEdit);
  end;

procedure TMyVisitor.VisitButton(Instance: TButton);
begin
  Instance.Caption := 'Hello World';
end;

procedure TMyVisitor.VisitEdit(Instance: TEdit);
begin
  Instance.Font.Style := [fsBold];
end;

procedure TMyVisitor.VisitPageControl(Instance: TPageControl);
begin
  Instance.ActivePageIndex := 0;
end;

procedure TForm40.Button1Click(Sender: TObject);
var
  visitor: TMyVisitor;
begin
  visitor := TMyVisitor.Create;
  try
    for var cmp in Self do
      visitor.Visit(cmp);
  finally
    visitor.Free;
  end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:41 Uhr.
Seite 3 von 3     123

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