Reputation: 3466
I am doing some finishing touches on my Windows application developed in Delphi XE6.
Currently, I become confused about window system menu, I mean the menu that appears when you click onto the icon in the title bar on the left.
I have defined two procedures:
// this inserts one additional command into the menu
procedure InsertCommand(Sender: TObject);
// this is obviously a handler of mouse clicks on that menu
procedure OnSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
The definitions follow:
const
ALWAYS_ON_TOP_ID = 1000;
var
HandleMenu: THandle;
sAlwaysOnTop: string;
procedure TFormMain.InsertCommand(Sender: TObject);
begin
// get the system menu handle and store it into form-level defined variable
HandleMenu := GetSystemMenu(Handle, False);
// just to make it nicer, I add a separator line
AppendMenu(HandleMenu, MF_SEPARATOR, 0, '');
// append "Always on Top" language localized string at the end of the menu
AppendMenu(HandleMenu, MF_STRING, ALWAYS_ON_TOP_ID, PChar(sAlwaysOnTop));
end;
procedure TFormMain.OnSysCommand(var Msg: TWMSysCommand);
begin
if Msg.CmdType = ALWAYS_ON_TOP_ID then
if GetMenuState(HandleMenu, ALWAYS_ON_TOP_ID, MF_BYCOMMAND) and MF_CHECKED = MF_CHECKED
then begin
FormStyle := fsNormal;
CheckMenuItem(HandleMenu, ALWAYS_ON_TOP_ID, MF_UNCHECKED);
end else begin
FormStyle := fsStayOnTop;
CheckMenuItem(HandleMenu, ALWAYS_ON_TOP_ID, MF_CHECKED);
end;
inherited;
end;
I now read that the right usage is:
Msg.CmdType and $FFF0
but if I use that, my code stops working.
From the official MSDN source, I quote:
In
WM_SYSCOMMAND
messages, the four low-order bits of thewParam
parameter are used internally by the system. To obtain the correct result when testing the value ofwParam
, an application must combine the value0xFFF0
with thewParam
value by using the bitwise AND operator.
Question is, do I have to avoid the $FFF0
mask, or is there a more proper way?
Upvotes: 2
Views: 351
Reputation: 54812
The documentation is accurate, the reason your code stops working when you test bitwise AND with $FFF0 is the constant you define is no good.
const
ALWAYS_ON_TOP_ID = 1000;
1000 in hexadecimal is 3E8, the lowest order hexadecimal digit should be 0 for the lowest four bits to be 0. IOW, binary 1111 is hexadecimal F, so you should leave the last digit to the system.
Set your constant in hexadecimal so you won't make a mistake. Just be careful to stay clear off the SC_...
range (which is $F000 ... $F###) when defining your constant. E.g.:
const
ALWAYS_ON_TOP_ID = $100; {256}
so now you can safely test
if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
...
Upvotes: 6