Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

recenter the form after altering form size

Tags:

resize

delphi

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;
like image 946
ikathegreat Avatar asked Dec 02 '25 05:12

ikathegreat


1 Answers

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;
like image 189
David Heffernan Avatar answered Dec 04 '25 22:12

David Heffernan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!