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
相关产品推荐
相关产品推荐

