Delphi:自定义 window 菜单:Msg.CmdType 和 $FFF0 需要说明
Delphi: custom window menu: Msg.CmdType and $FFF0 clarification needed
我正在对我在 Delphi XE6 中开发的 Windows 应用程序做最后的润色。
目前,我对 window 系统菜单感到困惑,我指的是当您单击左侧标题栏中的图标时出现的菜单。
我定义了两个程序:
// 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;
定义如下:
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;
我现在读到正确的用法是:
Msg.CmdType and $FFF0
但如果我使用它,我的代码将停止工作。
来自官方MSDN source,本人引用:
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.
问题是,我是否必须避开 $FFF0
掩码,还是有更合适的方法?
文档是准确的,你的代码停止工作的原因当你测试按位 AND 使用 $FFF0 是你定义的常量是不好的。
const
ALWAYS_ON_TOP_ID = 1000;
1000的十六进制是3E8,最低位的十六进制数应该是0,最低四位为0。IOW,二进制1111是十六进制的F,所以你应该把最后一位留给系统。
将常量设置为十六进制,这样就不会出错。在定义常量时,请小心远离 SC_...
范围(即 $F000 ... $F###)。例如:
const
ALWAYS_ON_TOP_ID = 0; {256}
所以现在你可以安全地测试了
if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
...
我正在对我在 Delphi XE6 中开发的 Windows 应用程序做最后的润色。
目前,我对 window 系统菜单感到困惑,我指的是当您单击左侧标题栏中的图标时出现的菜单。
我定义了两个程序:
// 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;
定义如下:
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;
我现在读到正确的用法是:
Msg.CmdType and $FFF0
但如果我使用它,我的代码将停止工作。
来自官方MSDN source,本人引用:
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.
问题是,我是否必须避开 $FFF0
掩码,还是有更合适的方法?
文档是准确的,你的代码停止工作的原因当你测试按位 AND 使用 $FFF0 是你定义的常量是不好的。
const
ALWAYS_ON_TOP_ID = 1000;
1000的十六进制是3E8,最低位的十六进制数应该是0,最低四位为0。IOW,二进制1111是十六进制的F,所以你应该把最后一位留给系统。
将常量设置为十六进制,这样就不会出错。在定义常量时,请小心远离 SC_...
范围(即 $F000 ... $F###)。例如:
const
ALWAYS_ON_TOP_ID = 0; {256}
所以现在你可以安全地测试了
if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
...