In the OnCreate
event of a modal form, I use SetWindowPlacement()
to restore the form's size and position that was previously saved. It works OK in a non-modal form, but it totally freezes on a modal form after a few seconds it appears.
Form1
is calling Form2
as modal.
I cannot use SetWindowPlacement()
in the OnShow
event because we get the exception:
class EInvalidOperation with message 'Cannot change Visible in OnShow or OnHide'.
The expecting result is to show a modal form on the last location before it was closed. SetWindowPlacement()
is the right function to use since it works OK on multiple monitors, even if one of the monitors is unplugged after the location was saved. If we don't consider this possibility, the form will just appear off-screen (hidden).
This is the short piece of code:
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2 := TForm2.Create(nil);
Form2.ShowModal;
FreeAndNil(form2);
end;
procedure TForm2.FormCreate(Sender: TObject);
begin
//Hard coded paremeters to make it simple
RestoreFormPosition(self, 100, 200, 301, 463);
end;
procedure TForm2.RestoreFormPosition(WhichForm: TForm; const pTop, pLeft, pHeight, pWidth: Integer);
var
recWndPlmt : TWindowPlacement;
begin
WhichForm.Position := poDesigned;
recWndPlmt.Length:= SizeOf(TWindowPlacement);
//GetWindowPlacement(WhichForm.Handle, @recWndPlmt);
recWndPlmt.rcNormalPosition.Top := pTop;
recWndPlmt.rcNormalPosition.Left := pLeft;
recWndPlmt.rcNormalPosition.Height := pHeight;
recWndPlmt.rcNormalPosition.Width := pWidth;
recWndPlmt.showCMD:= SW_SHOWNORMAL; //1;
SetWindowPlacement(WhichForm.Handle, @recWndPlmt);
end;
I don't know the root cause, but I can reproduce the problem in Delphi 12.2. For whatever reason, using SetWindowPlacement()
in this manner causes the Form's window to become disabled deep inside the VCL before the window is shown on-screen. In the OnShow
event, IsWindowEnabled()
returns False, whereas it returns True if SetWindowPlacement()
is not used.
I have opened a bug ticket with Embarcadero:
RSS-1915: Calling SetWindowPlacement() on a modal form disables the window
Until Embarcadero fixes this, calling EnableWindow()
in the OnShow
event solves the problem:
procedure TForm2.FormShow(Sender: TObject);
begin
EnableWindow(Handle, True);
end;
Using the Form's SetBounds()
method instead of SetWindowPlacement()
also avoids the problem:
//SetWindowPlacement(WhichForm.Handle, @recWndPlmt);
WhichForm.SetBounds(pLeft, pTop, pWidth, pHeight);