I have a combobox that has two options and the two options are triggering the form resizing. The idea is I'm going to hide and show additional controls based on the selection.
When I change the form width, the size changes as desired, however the form is now no longer in the center of the screen. Can I move the form's XY position back and forth while changing the form width?
procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject);
begin
if(SpecialFilesComboBox.ItemIndex = 0) then begin
//No special files
Width := 412;
Height := 423;
...
end
else begin
//Yes special files
Width := 893;
Height := 423;
...
end;
end;
Multi-monitor systems are common nowadays. Placing at the centre of the screen may spread the form across multiple monitors. That's undesirable.
So I'd centre the form on its monitor:
R := Form.Monitor.WorkAreaRect;
Form.Left := (R.Left+R.Right-Form.Width) div 2;
Form.Top := (R.Top+R.Bottom-Form.Height) div 2;
As @bummi points out, you can write:
Form.Position := poScreenCenter;
This almost works as you would wish. I will center the form on a screen. However, it always picks the default monitor. So using that code could result in your form being moved onto a different monitor which I think would never be desirable.
Rather forcing the form to the centre, you may decide instead to grow or shrink it on all sides:
procedure TReportFrm.SpecialFilesComboBoxChange(Sender: TObject);
var
NewLeft, NewTop, NewWidth, NewHeight: Integer;
begin
if(SpecialFilesComboBox.ItemIndex = 0) then begin
//No special files
NewWidth := 412;
NewHeight := 423;
...
end
else begin
//Yes special files
NewWidth := 893;
NewHeight := 423;
...
end;
NewLeft := Left + (Width-NewWidth) div 2;
NewTop := Top + (Top-NewHeight) div 2;
NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight);
BoundsRect := NewBoundsRect;
end;
And if you wanted to get really cute you'd adjust the bounds rect so that the newly sized and positioned form did not go off the edge of the monitor.
procedure MakeAppearOnScreen(var Rect: TRect);
const
Padding = 24;
var
Monitor: HMonitor;
MonInfo: TMonitorInfo;
Excess, Width, Height: Integer;
begin
Monitor := MonitorFromPoint(Point((Rect.Left+Rect.Right) div 2, (Rect.Top+Rect.Bottom) div 2), MONITOR_DEFAULTTONEAREST);
if Monitor=0 then begin
exit;
end;
MonInfo.cbSize := SizeOf(MonInfo);
if not GetMonitorInfo(Monitor, @MonInfo) then begin
exit;
end;
Width := Rect.Right-Rect.Left;
Height := Rect.Bottom-Rect.Top;
Excess := Rect.Right+Padding-MonInfo.rcWork.Right;
if Excess>0 then begin
dec(Rect.Left, Excess);
end;
Excess := Rect.Bottom+Padding-MonInfo.rcWork.Bottom;
if Excess>0 then begin
dec(Rect.Top, Excess);
end;
Excess := MonInfo.rcWork.Left+Padding-Rect.Left;
if Excess>0 then begin
inc(Rect.Left, Excess);
end;
Excess := MonInfo.rcWork.Top+Padding-Rect.Top;
if Excess>0 then begin
inc(Rect.Top, Excess);
end;
Rect.Right := Rect.Left+Width;
Rect.Bottom := Rect.Top+Height;
end;
Then the previous code sample would be altered like this:
NewBoundsRect := Rect(NewLeft, NewTop, NewLeft+NewWidth, NewTop+NewHeight);
MakeAppearOnScreen(NewBoundsRect);
BoundsRect := NewBoundsRect;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With