Verfolgen Sie den Code, um zu sehen, was passiert, ich kam mit der folgenden Anpassung.
procedure TForm1.WMWindowPosChanging(var Message: TWMWindowPosChanging);
var
MessageWidth: Integer;
begin
MessageWidth := Message.WindowPos.cx;
inherited;
if MessageWidth > Message.WindowPos.cx then
GroupBox1.Width := GroupBox1.Width - MessageWidth + Message.WindowPos.cx;
end;
Dies ist keine verallgemeinerte Lösung, aber es macht deutlich, was das Problem ist. VCL fragt nach einer Fenstergröße für seine Form, die vom Betriebssystem nicht gewährt wird, da sie größer als der Desktop ist. Von nun an wird das Formular wieder verankert, um das untergeordnete Steuerelement mit seiner festgelegten Entwurfszeit zu verankern, die größer ist als die Clientbreite des Formulars, sodass die rechte Seite des untergeordneten Steuerelements überläuft.
Eine andere Lösung kann sein, die Behandlung der Nachricht WM_GETMINMAXINFO
zu überschreiben, damit das Betriebssystem die angeforderte Breite gewährt.
Dies ist möglicherweise keine gute Lösung, denn dann wird das Formular größer als der Desktop sein.
In Bezug auf Ihre 'a' und 'b' Elemente, glaube ich nicht, 'b' ist möglich - oder zumindest nicht möglich, die VCL-Relayout selbst zu machen - weil VCL Anker Anwenden von Ankerregeln bis nach der Komponente (Form) wird geladen. Bis dahin ist die Breite des Formulars anders als die Entwurfszeitbreite, aber die Platzierung der untergeordneten Steuerelemente bleibt davon unberührt. Keine Menge an Forcing zum Layout wird sie wieder synchronisieren.
Es sollte jedoch möglich sein, alles von Grund auf neu zu berechnen, wenn Ihr eigener Code einen Verweis auf die Entwurfszeitbreite enthält. Der folgende Code ist nicht vollständig.
type
TForm1 = class(TForm)
..
private
FAdjustShrinkWidth, FAdjustShrinkHeight: Integer;
protected
procedure Loaded; override;
public
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer;
AHeight: Integer); override;
end;
...
procedure TForm1.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
TrackWidth, TrackHeight: Boolean;
begin
TrackWidth := AWidth = 1200;
TrackHeight := AHeight = ??;
inherited;
if TrackWidth and (Width < AWidth) then
FAdjustShrinkWidth := AWidth - Width;
if TrackHeight and (Height < AHeight) then
FAdjustShrinkHeight := AHeight - Height;
end;
procedure TForm1.Loaded;
procedure ReadjustControlAnchors(Control: TWinControl);
var
i: Integer;
begin
for i := 0 to Control.ControlCount - 1 do
if (akRight in Control.Controls[i].Anchors) or (akBottom in Control.Controls[i].Anchors) then begin
Control.Controls[i].Left := // some complex calculation depending on the anchors set;
Control.Controls[i].Top := // same as above;
Control.Controls[i].Width := // same as above;
Control.Controls[i].Height := // same as above;
if (Control.Controls[i] is TWinControl) and (TWinControl(Control.Controls[i]).ControlCount > 0) then
ReadjustControlAnchors(TWinControl(Control.Controls[i]));
end;
end;
begin
inherited;
ReadjustControlAnchors(Self);
end;
Ich habe keine Ahnung, wie Sie die Lücken im obigen Code ausfüllen. Das Lesen und Aufspüren von VCL-Code kann erforderlich sein, um die VCL-Verankerung zu imitieren.
Ich kann nichts für 'a' denken.
Update:
VCL hat tatsächlich eine Backdoor-links für eine Kontrolle seiner unmittelbaren Kinder über ihre Eltern Größe zu liegen, während sie zu verankern. Documentation erklärt es ein bisschen anders:
UpdateControlOriginalParentSize ist ein geschütztes Verfahren, das die Steuer Originalgröße der Mutter aktualisiert. Es wird intern verwendet, um die Ankerregeln des Steuerelements zu aktualisieren.
Wir können damit der Groupbox die beabsichtigte Originalgröße mitteilen.
type
TForm1 = class(TForm)
..
private
FWidthChange, FHeightChange: Integer;
protected
procedure UpdateControlOriginalParentSize(AControl: TControl;
var AOriginalParentSize: TPoint); override;
public
procedure SetBounds(ALeft: Integer; ATop: Integer; AWidth: Integer;
AHeight: Integer); override;
end;
...
procedure TForm1.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
var
RequestedWidth, RequestedHeight: Integer;
begin
RequestedWidth := AWidth;
RequestedHeight := AHeight;
inherited;
if csLoading in ComponentState then begin
if RequestedWidth <> Width then
FWidthChange := Width - AWidth;
if RequestedHeight <> Height then
FHeightChange := Height - AHeight;
end;
end;
procedure TForm1.UpdateControlOriginalParentSize(AControl: TControl;
var AOriginalParentSize: TPoint);
begin
inherited;
if akRight in AControl.Anchors then
AOriginalParentSize.X := AOriginalParentSize.X - FWidthChange;
if akBottom in AControl.Anchors then
AOriginalParentSize.Y := AOriginalParentSize.Y - FHeightChange;
end;
Ich stelle fest, wieder, dass dies die Form der unmittelbaren Kinder nur beeinflussen. Wenn das Groupbox Steuerelemente hostet, die rechts und unten verankert sind, muss es auch die gleiche Methode überschreiben.
Beachten Sie auch, dass dies nicht die Tatsache rückgängig macht, dass die Breite des Formulars geändert hat. Das heißt, wenn ein linkes verankertes Steuerelement ganz rechts im Formular vorhanden ist, ersetzt es sich nicht selbst gegenüber der Client-Grenze. Es wird sich so verhalten, als ob die Breite der Form verringert worden wäre, d.h. außerhalb der Sichtweite geblieben wäre.
Wie wäre es, wenn Sie die 'Align'-Eigenschaft der GroupBox auf' alTop' setzen? Dies entspricht der Aktivierung der Anker für den linken, oberen und rechten Anker, so dass sie gedehnt werden, wenn die Größe des übergeordneten Formulars geändert wird. –
Ich habe eine ähnliche Situation mit einem Frame in einer Form beobachtet. Wenn der Rahmen größer als das Formular ist, wird die Größe des Rahmens nicht auf die Abmessungen des Formulars geändert, selbst wenn die Eigenschaft Ausrichten auf Client festgelegt ist. Mit dem Rahmen ist der Trick kleiner zu machen und die Client-Eigenschaft den Job erledigen zu lassen. –