Delphi:自定义窗口菜单:需要Msg.CmdType和$ FFF0说明

Lin*_*eak 1 windows delphi window menu windows-messages

我正在对在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;
Run Code Online (Sandbox Code Playgroud)

定义如下:

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;
Run Code Online (Sandbox Code Playgroud)

我现在读到正确的用法是:

Msg.CmdType and $FFF0
Run Code Online (Sandbox Code Playgroud)

但如果我使用它,我的代码就会停止工作.

从官方MSDN来源,我引用:

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

问题是,我是否必须避开$FFF0面具,还是有更合适的方法?

Ser*_*yuz 5

文档是准确的,你的代码在按位测试时停止工作的原因和$ FFF0是你定义的常量是不好的.

const
  ALWAYS_ON_TOP_ID = 1000;
Run Code Online (Sandbox Code Playgroud)

十六进制的1000是3E8,最低的十六进制数字应该是0,最低的四位是0. IOW,二进制1111是十六进制F,所以你应该把最后一位数留给系统.

以十六进制设置常量,这样就不会出错.SC_...在定义常量时,请注意保持清除范围($ F000 ... $ F ###).例如:

const
  ALWAYS_ON_TOP_ID = $100; {256}
Run Code Online (Sandbox Code Playgroud)

所以现在你可以安全地测试了

  if Msg.CmdType and $FFF0 = ALWAYS_ON_TOP_ID then
    ...
Run Code Online (Sandbox Code Playgroud)