+2  A: 
Ken White
nice work, ken! thank you! a couple of tiny corrections for whoever may use this later: if <b>Msg</b>.CmdType = SC_MAXIMIZE then... SystemParametersInfo(SPI_GETWORKAREA, 0, <b>@R</b>, 0);
X-Ray
nice work, ken! thank you! a couple of tiny corrections for whoever may use this later: [reposted because HTML not rendered]. if Msg.CmdType = SC_MAXIMIZE then... SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0);
X-Ray
Thanks for the correction, X-Ray. I'll fix the typo (I knew I should have copied and pasted instead of retyping. <g>)
Ken White
i also discovered that it only works if the form is not set at design time to wsMaximized, this doesn't work. i can manage but if you know a solution to that as well that'd be wonderful. i can, of course change to only maximize at runtime.
X-Ray
Hmmm... Did you try using the code as well (without the message related stuff, of course) in FormCreate or FormShow? FormCreate might be too early... I never use wsMaximized myself; I leave that choice to the user. (You could separate out the API call and size code to a separate method, (more)
Ken White
and call that method from both the FormCreate/FormShow and in response to the WM_SysCommand message.
Ken White
Just had another thought... Instead of setting wsMaximized, just post your form a WM_SYSCOMMAND message in the FormCreate() event. That would call the existing message handler from my post, which would take care of the problem. PostMessage(Handle, WM_SYSCOMMAND, SC_MAXIMIZE, 0); should work.
Ken White
A: 

The solution proposed by Ken White has a few issues:

  • Maximize button stays active, can use resize handles on maximised window
  • Unable to restore window back to previous size.

So I propose the following:

// add to form object
procedure WMGetMinMaxInfo(var mmInfo : TWMGETMINMAXINFO); message WM_GETMINMAXINFO;

// implementation
procedure TfrmMain.WMGetMinMaxInfo(var mmInfo: TWMGETMINMAXINFO);
var
  R: TRect;
begin
  with mmInfo.MinMaxInfo^ do
  begin
    SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0);
    ptMaxPosition.X := R.Left;
    ptMaxPosition.Y := R.Top;
    ptMaxSize.X     := R.Right - R.Left;
    ptMaxSize.Y     :=  R.Bottom - R.Top-1;
  end;
end;

Not ideal, as I have to (for some reason) adjust the maxHeight by -1 in order for the default handler to not re-assert itself and move the window to -8,-8,... But it works for me.

Just Jules
sounds interesting. thank you; i'll give this a try when i get back to this!
X-Ray