By accident I came across the fact that reacting on message WM_SYSCOMMAND
is more complex than represented by the CONST values in lMessages.pp:
Yes, there are
undocumented system-reserved bits used by
WM_SYSCOMMAND, such as in the
$F001..$F009 range that your code is looking at.
This is documented on MSDN:
In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are used internally by the system. To obtain the correct result when testing the value of wParam, an application must combine the value 0xFFF0 with the wParam value by using the bitwise AND operator.
if (Msg.CmdType and $FF) = $20 then
The only
CmdType values whose lower 8 bits are
$20 are
SC_MINIMIZE (
$F020) and
SC_RESTORE (
$F120) (and only when those lower 4 bits are not being used by the system). You are pulling these two values out of the
CmdType and commenting them as "real" messages. But then your main
case block is also handling them too, making the
if block redundant.
This is just plain wrong. Per the documentation quoted above, you must mask the value of
CmdType, eg:
case Msg.CmdType and $FFF0 of
For instance, when
CmdType is
$F001, that is really
SC_SIZE (
$F000) + 1. And when
CmdType is
$F012, that is really
SC_MOVE (
$F010) + 2. And so on.
In fact,
$F012 is more commonly known as
SC_DRAGMOVE, which is used when dragging around a window by its title bar, and as such is useful when you want to manually initiate a drag of a window from an area other than its title bar, for instance when dragging a caption-less window.
Though, you really should not rely on the system bits having any particular meaning. They are private to the OS, and can change meaning from one version to another. But, in any case, there are some known meanings, see
https://stackoverflow.com/a/763273/65863.
With that said, since Microsoft doesn't want you looking at the private bits, you should end up with code that looks more like this instead:
procedure TChildForm.WMSysCommand(var Msg: TWmSysCommand);
begin
// https://docs.microsoft.com/en-us/windows/win32/menurc/wm-syscommand
//
// A window receives this message when the user chooses a command
// from the Window menu (formerly known as the system or control menu)
// OR when the user chooses the maximize button, minimize button,
// restore button, or close button.
case Msg.CmdType and $FFF0 of
SC_MOVE: // move form ..
begin
{$ifdef DEBUG_SUBUNIT}
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8) +' = SC_MOVE');
{$endif}
end;
SC_CLOSE: // close form ..
begin
{$ifdef DEBUG_SUBUNIT}
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8) +' = SC_CLOSE');
{$endif}
end;
SC_RESTORE: // normalize form ..
begin
{$ifdef DEBUG_SUBUNIT}
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8) +' = SC_RESTORE');
{$endif}
end;
SC_MAXIMIZE: // maximize form ..
begin
StoreBounds;
{$ifdef DEBUG_SUBUNIT}
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8) +' = SC_MAXIMIZE');
{$endif}
end;
SC_MINIMIZE: // minimize form ..
begin
// https://microsoft.public.vc.mfc.narkive.com/EtOQGNmk/sc-restore
// https://www.askingbox.de/frage/delphi-auf-minimieren-einer-form-reagieren-onminimize
{$ifdef DEBUG_SUBUNIT}
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8) +' = SC_MINIMIZE');
{$endif}
end
// => https://stackoverflow.com/questions/9704075/how-to-detect-when-the-form-is-being-maximized
else
begin
Memo1.Append( 'WMSysCommand() .. $' +IntToHex( Msg.CmdType, 8));
inherited;
end;
end;
end;