1

Many of my application forms inherit from a base form which loads the saved window size, position and state recorded during FormClose and applies it during FormShow.

The inherited; line in the descendant version of FormShow is in the usual place at the start of the method, and is generally followed by a fair amount of code that requires the visual components on the form to have been created so they can be manipulated and set up.

The problem I am having is that the form is usually hidden until the end of the descendent FormShow event, which is the expected behaviour, unless the WindowState is being set to wsMaximized in the ancestor class FormShow event. In that case, the form becomes visible as soon as the inherited; line is executed, and you get to watch as the remaining visual elements get organised.

When setting the WindowState property of a VCL.Forms.TForm, the following code is executed:

procedure TCustomForm.SetWindowState(Value: TWindowState);
const
  ShowCommands: array[TWindowState] of Integer =
    (SW_SHOWNORMAL, SW_MINIMIZE, SW_SHOWMAXIMIZED);
begin
  if FWindowState <> Value then
  begin
    FWindowState := Value;
    if not (csDesigning in ComponentState) then
    begin
      if Showing then
        ShowWindow(Handle, ShowCommands[Value])
      else if HandleAllocated and (FWindowState = wsMaximized) then
        RecreateWnd;
    end;
  end;
end;

The apparent cause of the issue is somewhere in that method; either the ShowWindow or the RecreateWnd, which seems to be triggering the form to be immediately painted.

Apart from moving my LoadFormState(Self); method from TBaseForm.FormShow to TBaseForm.FormActivate, is there any other way to set the form to be maximized without it actually showing the form?

SiBrit
  • 1,460
  • 12
  • 39

1 Answers1

1

You should not be calling your LoadFromState procedure either from TBaseForm.FormShow or TBaseForm.FormActivate.

TBaseForm.FormShow is called every time visibility of your form changes from False to True.
So for instance if you hide your from when showing another and then show it again after another form is closed TBaseForm.FormShow will fire and thus you will load form's dimensions and position from the saved state which might not be the same state as of when the form was hidden. User might have moved and resized the from since application was started.
This will lead to form moving its position without users wish to do so and thus it will annoy your users as hell.

Also don't use TBaseForm.FormActivate as this fires every time Form receives focus. So changing focus from another back to this one will the TBaseForm.FormActivate and thus change your form dimensions and position to the saved state which might not be teh state when form lost its focus.

The correct place for you to call your LoadFormState procedure with which you load initial properties of your form is within the forms constructor.

SilverWarior
  • 7,372
  • 2
  • 16
  • 22
  • I agree that using FormActivate would probably require some logic to indicate that the first time it fires it can load the form state, but subsequent firings should do nothing. Not worried about FormShow as I never use FormHide. In the end I coded the LoadFormState at the end of the FormShow event for every descendent form that needed it. – SiBrit Dec 15 '20 at 21:23
  • So would using FormShow as it can also be called multiple times during your application execution. – SilverWarior Dec 15 '20 at 21:28
  • No idea what you're talking about. Yes. FormShow can be called multiple times, but only if the user closes and reopens the form, and since I store the form state on closing, when the form is re-opened it would reload the dimensions and position as it was when it was closed, so yes, the state is always the same. Since my forms are never hidden, only ever destroyed, the FormShow event cannot execute more than once for any given instance of a form, hence why my LoadFormState is the last bit of code in the FormShow event. FormShow is not fired if you minimise/maximise a form then restore it. – SiBrit Dec 16 '20 at 02:46