Tracking the code to find out what will happen, I came up with the following setting.
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;
This is not a generalized solution, but it is clear what the problem is. VCL asks for the window size for its form, which is not provided by the OS, since it is larger than the desktop. From this moment, the form resumes binding the child control with the specified width of its design, which is greater than the width of the form client, therefore the right side of the child control overflows.
Another solution might be to override WM_GETMINMAXINFO message processing to provide the OS with a given width.
procedure TForm1.WMGetMinMaxInfo(var Message: TWMGetMinMaxInfo); begin inherited; Message.MinMaxInfo.ptMaxTrackSize.X := 1200; end;
This may not be a good solution, because the form will be larger than the desktop.
As for your positions βaβ and βbβ, I donβt think that βbβ is possible - or at least it is not possible to relay the VCL on its own, because the VCL delays the application of the binding rules until the component (form) loading is done. By that time, the width of the form is different from the width of the development time, but the placement of the child controls does not change. No amount of force to build will force them to sync again.
However, you can recalculate everything from scratch if your own code contains a link to the width of the design time. The following is an incomplete code.
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;
I do not know how to fill in the gaps in the above code. Reading and tracking VCL code may be required to simulate VCL bindings.
I can't think of anything for an "a".
Update:VCL actually left a backdoor for management to lie to their immediate children about their parental size while they are tied. The documentation explains this a little differently:
UpdateControlOriginalParentSize is a protected method that updates the original size of the parent control. It is used to update the control binding rule.
We can use it to tell the group box the estimated original size.
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;
Once again, I want to note that this will affect only children with immediate forms. If a group package contains controls that snap to the right and bottom, it must also override the same method.
Also note that this does not negate the fact that the width of the form has changed. This, if there was a left-bound control that is in the far right corner of the form, it would not replace itself with the clientβs border. It will act as if the width of the form was reduced, that is, remained out of sight.