Hallo,
Ja das sieht komisch aus, aber dank
R := Control.ClientRect;
werden genau(nur) R.Right und R.Bottom gesetzt.
Nur R.Top und R.Left muss man sich 'umständlich' via
R.TopLeft := Self.ScreenToClient(Control.ClientToScreen(Point(0, 0)));
holen.
Auf Height und Width bin ich in diesem Zusammenhang gar nicht gekommen.
Ich habe aber das ursprüngliche Problem anders gelöst und eine Anleihe bei TObjectList genommen. Heraus gekommen sind:
Delphi-Quellcode:
TRectEntry = class(TObject)
private
FLeft : Integer;
FTop : Integer;
FRight : Integer;
FBottom : Integer;
FControl : TControl;
public
constructor Create(Control : TControl; Rect : TRect);
destructor Destroy; override;
property Left : Integer read FLeft;
property Top : Integer read FTop;
property Right : Integer read FRight;
property Bottom : Integer read FBottom;
property Control: TControl read FControl;
end;
TSortOrder = (soTopBottom, soLeftRight);
TRectList = class(TList)
private
FOwnsObjects: Boolean;
FSortOrder : TSortOrder;
procedure SetSortOrder(Value : TSortOrder);
protected
procedure Notify(Ptr: Pointer; Action: TListNotification); override;
function GetItem(Index: Integer): TRectEntry;
function FindNextIndex(X : Integer) : Integer;
public
constructor Create; overload;
constructor Create(AOwnsObjects: Boolean); overload;
function Add(aRectEntry : TRectEntry): Integer;
property Items[Index: Integer]: TRectEntry read GetItem;
property OwnsObjects: Boolean read FOwnsObjects write FOwnsObjects;
property SortOrder : TSortOrder read FSortOrder write SetSortOrder default soTopBottom;
end;
In der RectList sind die beiden Funktionen Add und FindNextIndex, die jenigen, die
bei mir zum Ziel führen:
Delphi-Quellcode:
...
constructor TRectEntry.Create(Control : TControl; Rect : TRect);
begin
inherited Create;
FControl := Control;
FLeft := Rect.Left;
FTop := Rect.Top;
FRight := Rect.Right;
FBottom := Rect.Bottom;
end;
...
function TRectList.FindNextIndex(X : Integer) : Integer;
var
I : Integer;
begin
Result:= -1;
case SortOrder of
soTopBottom : begin
for I := 0 to Count - 1 do
begin
if Items[I].Top > X then
begin
Result := I;
Break;
end
else
if Items[I].Bottom = X then
begin
if I = Count-1 then Result := -1
else Result := I+1;
Break;
end;
end;
end;
soLeftRight : begin
for I := 0 to Count - 1 do
begin
if Items[I].Left > X then
begin
Result := I;
Break;
end
else
if Items[I].Right = X then
begin
if I = Count-1 then Result := -1
else Result := I+1;
Break;
end;
end;
end;
end;
end;
function TRectList.Add(aRectEntry : TRectEntry): Integer;
var
Idx : Integer;
begin
Result := -1;
case SortOrder of
soTopBottom: if Count > 0 then
begin
Idx := FindNextIndex(aRectEntry.Top);
if (Idx > -1) then
begin
Insert(Idx, aRectEntry);
Result := IndexOf(aRectEntry);
end
else
Result := inherited Add(aRectEntry);
end
else
Result := inherited Add(aRectEntry);
soLeftRight: if Count > 0 then
begin
Idx := FindNextIndex(aRectEntry.Left);
if (Idx > -1) then
begin
Insert(Idx, aRectEntry);
Result := IndexOf(aRectEntry);
end
else
Result := inherited Add(aRectEntry);
end
else
Result := inherited Add(aRectEntry);
end;
end;
Gefüllt wird die RectList über so:
Delphi-Quellcode:
...
for I := 0 to ControlCount - 1 do
begin
R := Controls[I].ClientRect;
R.TopLeft := ScreenToClient(Controls[I].ClientToScreen(Point(0,0)));
R.Right := R.Left + R.Right;
R.Bottom := R.Top + R.Bottom;
FRectList.Add(TRectEntry.Create(Controls[I], R));
end;
Etwas besseres ist mir nicht eingefallen, aber vielleicht weiß ja hier jemand wie
das Problem eleganter gelöst werden kann.