Setting the WindowState is showing the form

626 views Asked by At

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?

1

There are 1 answers

3
SilverWarior On BEST ANSWER

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.