Search code examples
delphiwindows-10vcldelphi-10.1-berlin

Dynamically assigning form size before maximize loses assigned values


I have an application which always starts initially maximized. This consists of putting Self.WindowState := wsMaximized; in the OnCreate of the main form.

Just before that, I'm assigning what should be the default dimensions of the main form, if the user were to change the window state to wsNormal.

So, in short, the main form's OnCreate handler looks something like:

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  Width:= 1300;
  Height:= 800;
  WindowState:= wsMaximized;
end;

Theoretically, I could assign these dimensions in design-time, and that does what I need. However, due to the size of my screen, and thus the IDE, the whole form is not visible at one glance without scrolling. In design, I keep the form size small, so I can see everything. But in runtime, I need to assign these default dimensions, and then maximize it by default. When the user changes the window state out of maximized, I expect it to go to those dimensions I dynamically assigned.

The issue is that it seems to lose those dimensions after maximizing the form, and it reverts back to whatever values were in design-time. If I comment out the line WindowState:= wsMaximized; then it shows the form in the desired default dimensions. However, maximizing it seems to overwrite and ignore these values I had just assigned before it.

How can I create and show my main form maximized by default, while at the same time dynamically assigning the default size, without my assigned values getting lost?


Solution

  • (Confirmed with 10.3.3.) The exact origin of this problem I cannot pinpoint, but a reasonable cause would be that during the constructor the form component is being read and that previous sizes seem to be explicitly backed up:

    procedure TControl.SetWidth(Value: Integer);
    begin
      SetBounds(FLeft, FTop, Value, FHeight);
      Include(FScalingFlags, sfWidth);
      if csReading in ComponentState then
        FExplicitWidth := FWidth;
    end;
    

    A possible solution is to set the desired sizes in the OnCreate event, like you are doing now, but postpone setting the desired WindowsState until the OnShow event.

    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Width := 1300;
      Height := 800;
    end;
    
    procedure TForm1.FormShow(Sender: TObject);
    begin
      WindowState := wsMaximized;
    end;
    

    Of course, you probably should prevent consecutive calls by using a one-off mechanism. Please take a look at wsMaximized forms do not appear maximized too.