德尔福:自定义窗口菜单:需要澄清Msg.CmdType和$FFF 0



我正在对用Delphi XE6开发的Windows应用程序进行一些最后的润色。

目前,我对窗口系统菜单感到困惑,我的意思是单击左侧标题栏中的图标时出现的菜单。

我定义了两个程序:

// 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官方来源,我引用:

WM_SYSCOMMAND消息中,wParam参数的四个低位由系统内部使用。为了在测试wParam值时获得正确的结果,应用程序必须使用按位 AND 运算符将值0xFFF0wParam值组合在一起。

问题是,我是否必须避免使用$FFF0口罩,或者有更合适的方法?

文档是准确的,当您按位测试时代码停止工作的原因 $FFF 0 是您定义的常量是不好的。

const
  ALWAYS_ON_TOP_ID = 1000;
十六进

制中的 1000 是 3E8,最低十六进制数字应为 0,最低四位为 0。IOW,二进制 1111 是十六进制 F,因此您应该将最后一个数字留给系统。

将常量设置为十六进制,这样您就不会犯错误。在定义常量时,请注意清除SC_...范围(即 $F 000 ... $F###(。例如:

const
  ALWAYS_ON_TOP_ID = $100; {256}

所以现在您可以安全地测试

  if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
    ...

最新更新