![]() |
.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 |
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; |
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; |
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'; |
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? |
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
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:
zurückgeben, was ja problemlos mit for-in iteriert werden kann, wäre das dann auch un-objektorientiert?
TArray<TControl>
Immerhin wird sowas ja bereits an vielen Stellen in Delphi gemacht, z.B.
Delphi-Quellcode:
.
TStringList.ToStringArray
Zitat:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
Delphi-Quellcode:
Doch ist doch objektorientiert. Oder wie sollte es nach Deiner Meinung aussehen, wenn es objektorientiert wäre?
for var ctrl in ControlsOf<TButton> do
ctrl.Caption := 'Hello World'; |
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'; |
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
für Components gibt es bereits einen Enumerator
Delphi-Quellcode:
for var C in IrgendeineTComponentInstanz do
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
Zitat:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Hallo zusammen,
sorry, konnte mir das gestern nicht mehr genau ansehen - war ein bisschen knapp an Zeit... Wenn ich mir jetzt das mit
Code:
ansehe, dann ist das natürlich
Panel1.ControlsOf<TButton>
1. absolut objektorientiert und 2. mit der Angabe der Control-Typen, die man haben will, auch noch praktischer als eine reine Auflistung. Das werde ich auf jeden Fall nutzen! Vielen Dank dafür! Gruß Freejay |
AW: .Controls und .Components nicht als Auflistung nutzbar?
Stefan Glienke hat gestern noch ein wenig Hand angelegt und ich möchte euch das Ergebnis nicht vorenthalten:
Zitat:
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; |
AW: .Controls und .Components nicht als Auflistung nutzbar?
:thumb:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
So, hier noch eine generische Alternative wenn es auf Performance nicht ganz so ankommt (wegen der anonymen Methode). Kann man dann allerdings auch leicht in anderen Situationen einsetzen.
Delphi-Quellcode:
type
TEnumWrapper<T: class> = record type TGetItemFunc = TFunc<Integer, TObject>; TEnumerator = record private FIndex: Integer; FCount: Integer; FCurrent: T; FGetItem: TGetItemFunc; public function MoveNext: Boolean; inline; property Current: T read FCurrent; end; private FCount: Integer; FGetItem: TGetItemFunc; public constructor Create(ACount: Integer; AGetItem: TGetItemFunc); function GetEnumerator: TEnumerator; inline; end; type TComponentHelper = class helper for TComponent public function ComponentsOf<T: TComponent>: TEnumWrapper<T>; inline; end; type TWinControlHelper = class helper for TWinControl public function ControlsOf<T: TControl>: TEnumWrapper<T>; inline; end; implementation { TEnumWrapper<T> } constructor TEnumWrapper<T>.Create(ACount: Integer; AGetItem: TGetItemFunc); begin FCount := ACount; FGetItem := AGetItem; end; function TEnumWrapper<T>.GetEnumerator: TEnumerator; begin Result.FCount := FCount; Result.FGetItem := FGetItem; Result.FIndex := -1; end; function TEnumWrapper<T>.TEnumerator.MoveNext: Boolean; var cmp: TObject; begin repeat Inc(FIndex); if FIndex < FCount then begin cmp := FGetItem(FIndex); if cmp.InheritsFrom(T) then begin FCurrent := T(cmp); Exit(True); end; Continue; end; until True; Result := False; end; { TComponentHelper } function TComponentHelper.ComponentsOf<T>: TEnumWrapper<T>; begin Result := TEnumWrapper<T>.Create(ComponentCount, function(Index: Integer): TObject begin Result := Components[Index]; end); end; { TWinControlHelper } function TWinControlHelper.ControlsOf<T>: TEnumWrapper<T>; begin Result := TEnumWrapper<T>.Create(ControlCount, function(Index: Integer): TObject begin Result := Controls[Index]; end); end; |
AW: .Controls und .Components nicht als Auflistung nutzbar?
Tolle Arbeit und toll, dass ihr euch die ganze Mühe macht, muss man mal sagen. :thumb:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
"remember me" funktioniert auch nicht... |
AW: .Controls und .Components nicht als Auflistung nutzbar?
Ich hatte das Problem noch nicht.
|
AW: .Controls und .Components nicht als Auflistung nutzbar?
Zitat:
Wie sieht es denn bei folgender Konstellation aus?
Delphi-Quellcode:
Man bräuchte dann ja 3 Durchläufe, anstatt, wie im Beispiel zusehen, nur einen Durchlauf.
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]; |
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:
Eigentlich ist das aber ein Anwendungsfall für das
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; ![]()
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 06:20 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz