title: wsMaximized forms do not appear maximized
body: <p>Setting a form to <code>WindowState = wsMaximized</code> will sometimes cause the form to be maximized but not:</p>
  
  <p><img src="https://i.stack.imgur.com/L3L5l.png" alt="enter image description here"></p>
  
  <p>Long-time bug: this is a question I first asked in the Borland newsgroups in 2003:</p>
  
  <ul>
  <li><a href="https://groups.google.com/forum/#!msg/borland.public.delphi.vcl.components.using/_WArmfPxKxI/e9EFjCqsZ7sJ" rel="noreferrer">Accepted fix for WindowState = wsMaximized?</a></li>
  </ul>
  
  <p>and then again in 2006:</p>
  
  <ul>
  <li><a href="https://groups.google.com/d/msg/borland.public.delphi.ide.general/h8uHgpShA_k/cpl0vWExgQEJ" rel="noreferrer">wsMaximized breaks it, NOT caused by Position=poScreenCenter, reproducible dfm</a></li>
  </ul>
  
  <p>and then again in 2008:</p>
  
  <ul>
  <li><a href="https://groups.google.com/d/msg/borland.public.delphi.nativeapi.win32/ZtmwPTPD5Rw/n4w-QR3yZ_oJ" rel="noreferrer">Forms not starting maximized</a></li>
  </ul>
  
  <p>Someone asked it on the Embarcadero forums in 2012:</p>
  
  <ul>
  <li><a href="https://forums.embarcadero.com/message.jspa?messageID=465790" rel="noreferrer">Thread: Application not starting with maximized window</a></li>
  </ul>
  
  <p>Now it's time to port the 18 year old bug to Stackoverflow. Maybe someone's finally figured out a workaround.</p>
  
  <p><strong>Steps to reproduce</strong>:</p>
  
  <p>My posts contained half a dozen failure modes, but the easiest is:</p>
  
  <ul>
  <li><p>Drop a <code>Label</code> and an <code>Edit</code> on a form:</p>
  
  <p><img src="https://i.stack.imgur.com/sqvfL.png" alt="enter image description here"></p></li>
  <li><p>Add an <code>OnEnter</code> event for the <code>TEdit</code>:</p>
  
  <pre><code>procedure TForm1.Edit1Enter(Sender: TObject);
  begin
     Label1.Font.Style := Label1.Font.Style + [fsBold];
  end;
  </code></pre></li>
  <li><p>and set the form: </p>
  
  <ul>
  <li><code>WindowState</code> to <strong>wsMaximized</strong></li>
  <li><code>AutoScroll</code> to <strong>False</strong></li>
  </ul></li>
  </ul>
  
  <p>And bazinga, fails.</p>
  
  <p>One of the other set of steps from the 2008 post:</p>
  
  <blockquote>
    <ol>
    <li>Create a new app and a form.</li>
    <li>Set the form to maximized (WindowState = wsMaximized) at design time.</li>
    <li>Drop a ListView control on the form</li>
    <li><p>During OnShow, add 20 empty items to the list view:</p>
  
  <pre><code>procedure TForm1.FormShow(Sender: TObject);
  var
       i: Integer;
  begin
       for i := 1 to 20 do
            ListView1.Items.Add;
  
  end;
  </code></pre></li>
    <li><p>Set the form's AutoScroll property to false (AutoScroll = False) at  design time</p></li>
    </ol>
  </blockquote>
  
  <p>Of course what I'm <em>not</em> after is <em>"fixed in version <code>n</code> of RadStudio. Just use that"</em>. 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).</p>
  
  <p><strong>Note:</strong> Changing <code>Position</code> from <strong>poDesigned</strong> to <em>anything else</em> doesn't fix it.</p>
  
  <h1>Workaround</h1>
  
  <p>A horrible, ugly, awful, disgusting, workaround I had been using was to start a timer during <code>OnShow</code>, and then when the timer fires, maximize the form:</p>
  
  <pre><code>procedure TForm1.tmrVclMaximizeHackTimer(Sender: TObject);
  begin
     Self.WindowState := wsMaximized;
  end;
  </code></pre>
  
  <p>I later improved this hack to post a message during <code>OnShow</code>; which is essentially the same as a timer message, without having to use a timer:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>Sometimes I invent the <code>OnAfterShow</code> event that Delphi never did:</p>
  
  <pre><code>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;
  </code></pre>
  
  <p>But no hacks are better than hacks.</p>