wsMaximized forms do not appear maximized

Ian Boyd picture Ian Boyd · Oct 20, 2013 · Viewed 14.3k times · Source

Setting a form to WindowState = wsMaximized will sometimes cause the form to be maximized but not:

enter image description here

Long-time bug: this is a question I first asked in the Borland newsgroups in 2003:

and then again in 2006:

and then again in 2008:

Someone asked it on the Embarcadero forums in 2012:

Now it's time to port the 18 year old bug to Stackoverflow. Maybe someone's finally figured out a workaround.

Steps to reproduce:

My posts contained half a dozen failure modes, but the easiest is:

  • Drop a Label and an Edit on a form:

    enter image description here

  • Add an OnEnter event for the TEdit:

    procedure TForm1.Edit1Enter(Sender: TObject);
    begin
       Label1.Font.Style := Label1.Font.Style + [fsBold];
    end;
    
  • and set the form:

    • WindowState to wsMaximized
    • AutoScroll to False

And bazinga, fails.

One of the other set of steps from the 2008 post:

  1. Create a new app and a form.
  2. Set the form to maximized (WindowState = wsMaximized) at design time.
  3. Drop a ListView control on the form
  4. During OnShow, add 20 empty items to the list view:

    procedure TForm1.FormShow(Sender: TObject);
    var
         i: Integer;
    begin
         for i := 1 to 20 do
              ListView1.Items.Add;
    
    end;
    
  5. Set the form's AutoScroll property to false (AutoScroll = False) at design time

Of course what I'm not after is "fixed in version n of RadStudio. Just use that". I'm looking for an actual fix (if there is one); which could include quoting relevant changes to the VCL source when CodeGear finally did fix it. (If it is even fixed).

Note: Changing Position from poDesigned to anything else doesn't fix it.

Workaround

A horrible, ugly, awful, disgusting, workaround I had been using was to start a timer during OnShow, and then when the timer fires, maximize the form:

procedure TForm1.tmrVclMaximizeHackTimer(Sender: TObject);
begin
   Self.WindowState := wsMaximized;
end;

I later improved this hack to post a message during OnShow; which is essentially the same as a timer message, without having to use a timer:

const
  WM_MaximizeWindow = WM_APP + $03;

procedure TForm1.FormShow(Sender: TObject);
begin
  if (Self.WindowState = wsMaximized) then
  begin
     Self.WindowState := wsNormal;
     PostMessage(Self.Handle, WM_MaximizeWindow , 0, 0);
  end;
end;

private
   procedure WMMaximizeWindow(var Message: TMessage); message WM_MaximizeWindow;

procedure TForm1.WMMaximizeWindow(var Message: TMessage);
begin
   Self.WindowState := wsMaximized;
end;

Sometimes I invent the OnAfterShow event that Delphi never did:

const
  WM_AfterShow = WM_APP + $02;

procedure TForm1.FormShow(Sender: TObject);
begin
  PostMessage(Self.Handle, WM_AfterShow, 0, 0);
  if (Self.WindowState = wsMaximized) then
  begin
     Self.WindowState := wsNormal;
     FMaximizeNeeded := True;
  end;
end;

private
   procedure WMAfterShow(var Message: TMessage); message WM_AfterShow;

procedure TForm1.WMAfterShow(var Message: TMessage);
begin
   if FMaximizeNeeded then
   begin    
      FMaximizeNeeded := False;
      Self.WindowState := wsMaximized;
   end;
end;

But no hacks are better than hacks.

Answer

kobik picture kobik · Nov 1, 2013

I Can reproduce with D7/Win7.

I don't use wsMaximized at all (similar random problems as you describe).

Workaround: