Why is my Delphi form control clipped when my form is larger than my screen?

The scenario is this:

  • I created a Delphi form (XE2).
  • One TGroupBox (or another control) is stretched on it, so it takes up the entire width of the form with the top.
  • The right anchor (in addition to the left and top) on the TGroupBox is installed.
  • The width of the shape is set to 1200 pixels (to illustrate the point).

If I run this application on a monitor whose Screen.Width property is Screen.Width than 1200 pixels (I start without any DPI AFAIK virtualization), then TGroupBox displays, as expected.

However, if the width of the monitor is less than 1200 pixels, then the right side of the control is not on the screen, regardless of how to resize the form.

I overridden the Create() method of my form using the override; and confirmed that I am setting the width property correctly, however the control is still cropping.

Can anyone advise how:

a) set the width property of the form so that it affects the positioning of child components or ...

b) propose a way to force relay all child components after the form is rendered?

+5
source share
1 answer

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.

+3
source

All Articles