You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi自定义窗口菜单:Msg.CmdType与$FFF0相关疑问求解

关于Delphi XE6中WM_SYSCOMMAND的CmdType与$FFF0的说明

嗨,我来帮你把这个点讲清楚——在处理Windows系统菜单的WM_SYSCOMMAND消息时,Msg.CmdType和$FFF0的配合是Windows系统的硬性要求,核心目的是过滤掉命令参数里的附加标志位。

为什么需要$FFF0?

Windows在发送WM_SYSCOMMAND消息时,会给CmdType的低4位附加一些额外信息(比如用户点击标题栏时的具体位置、是否按住了修饰键等),这些位并不是命令本身的一部分。而$FFF0是一个十六进制掩码,它的二进制形式是1111111111110000,和CmdType做与运算后,就能清除低4位的无关标志,得到纯粹的系统命令ID。

举个例子:假设系统发送的Msg.CmdType是SC_CLOSE or HT_CAPTION(也就是关闭命令加上标题栏点击的位置标志),直接用这个值和SC_CLOSE比较会不相等,但经过Msg.CmdType and $FFF0处理后,就会得到纯粹的SC_CLOSE,这样就能正确匹配命令。

在你的OnSysCommand过程里怎么用?

给你一个实用的代码示例,照着这个逻辑处理就不会错:

procedure TYourForm.OnSysCommand(var Msg: TWMSysCommand);
var
  PureCommand: Integer;
begin
  // 先过滤掉低4位的附加标志
  PureCommand := Msg.CmdType and $FFF0;

  case PureCommand of
    // 如果你插入了自定义命令,比如SC_MY_CUSTOM = $0800(要大于SC_USER)
    SC_MY_CUSTOM:
      begin
        // 处理你的自定义命令逻辑
        ShowMessage('自定义系统菜单命令被点击');
        Msg.Result := 0; // 告诉系统已经处理了这个消息
        Exit;
      end;
    // 处理系统默认命令(可选,如果你需要重写默认行为)
    SC_CLOSE:
      begin
        if MessageDlg('确定要关闭吗?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
          inherited // 调用默认关闭逻辑
        else
          Msg.Result := 0; // 取消关闭
      end;
    // 其他系统命令交给默认处理
    else
      inherited;
  end;
end;

关于自定义菜单命令的小提示

你在InsertCommand里插入自定义命令时,要注意命令ID的取值:

  • 系统默认的SC_*常量(比如SC_CLOSE、SC_MINIMIZE)都小于SC_USER($0800)
  • 自定义命令建议使用大于等于SC_USER的值,避免和系统命令冲突

这样处理后,你的系统菜单自定义命令和默认命令就能被正确识别和处理啦。

内容的提问来源于stack exchange,提问作者Vlastimil Burián

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:46:40