翻译《The Old New Thing》 - Restating the obvious about the WM_COMMAND message

news2024/10/7 4:28:12

Restating the obvious about the WM_COMMAND message - The Old New Thing (microsoft.com)icon-default.png?t=N7T8https://devblogs.microsoft.com/oldnewthing/20060302-10/?p=32093

Raymond Chen 2006年03月02日


关于 WM_COMMAND 消息的显而易见的知识点补充

 

简要

        本文详细解释了 WM_COMMAND 消息的用途和参数,包括三种触发该消息的情景:菜单选择、控件通知和加速键击。wParam 参数的高字节表示通知代码,低字节表示控件或菜单项的标识符。lParam 参数是控件句柄,如果是菜单或加速器则为 NULL。文章还讨论了 WM_NOTIFYWM_COMMAND 的区别,并指出在早期 Windows 版本中,由于 WM_NOTIFY 不可用,控件通常使用 WM_COMMAND 进行通知。最后,文中通过代码示例说明了如何手动生成这些消息。

正文

        我对 MSDN 上关于 WM_COMMAND 消息的文档很满意,但为了更进一步的完整性,我将陈述一些显而易见的内容,希望你们,亲爱的读者,能够利用这些技术来填补MSDN其他部分的空白。

  WM_COMMAND 消息的一行摘要说: “当用户从菜单中选择一个命令项,当一个控件向其父窗口发送一个通知消息,或者当一个加速键击被翻译时,会发送 WM_COMMAND 消息。”

        简而言之,有三种情况会生成 WM_COMMAND 消息,即上述列出的三种。你应该将 WM_COMMAND 消息的菜单和加速器情况视为控件情况的特殊情况。

  wParam 参数的高字节“如果消息来自控件,则指定通知代码。” 这里的“控件”是什么意思? 记住,你必须根据上下文来考虑事物。 WM_COMMAND 消息是在 Win32 的一般上下文中,特别是窗口管理器的上下文中提出的。 通常称为“控件”的窗口,如编辑框、按钮和列表框,以及“公共控件库”中的所有窗口类都是如此。 在窗口管理器的世界里,一个“控件”是一个窗口,其目的是为其父窗口提供一定程度的交互性(在静态控件的情况下,可能根本没有交互性)。

  WM_COMMAND 主要用于对话框的上下文,进一步强调了这里的“控件”一词只是“子窗口”的同义词。

        “通知代码”在这里意味着什么? 控件通知代码是由控件本身定义的任意16位值。 按照惯例,它们被命名为 xxN_xxxx,其中“N”代表“通知”。 然而,要小心,不要将其与 WM_NOTIFY 消息相关联的通知代码混淆。 幸运的是,每个通知代码在其文档中都指定了它是作为 WM_COMMAND 通知还是 WM_NOTIFY 通知到达的。

        现代控件设计师更有可能使用 WM_NOTIFY 通知,因为它们允许随通知传递额外的信息。 相比之下,WM_COMMAND 消息只传递通知本身;WM_COMMAND 消息的其他参数是强制的,如下所示。

        如果 WM_NOTIFYWM_COMMAND 更优越,为什么一些控件使用 WM_COMMAND? 因为 WM_NOTIFY 直到 Windows 95 才可用。 在 Windows 95 之前编写的控件不得不满足于使用 WM_COMMAND 消息。

        “如果消息来自加速器,这个值【wParam 参数的高字节】是 1。” 记住,我们仍然在窗口管理器的上下文中,特别是在 WM_COMMAND 消息的上下文中。 这里的加速器指的是在消息循环中调用 TranslateAccelerator 生成的消息。

        “如果消息来自菜单,这个值是零。” 如果 WM_COMMAND 消息是由用户从菜单中选择一个项触发的,那么 wParam 的高字节是零。

  wParam 参数的低字节“指定菜单项、控件或加速器的标识符。” 菜单项或加速器的标识符是你在菜单或加速器模板中与之关联的命令代码,或者(在菜单项的情况下)当你使用像 InsertMenuItem 这样的函数手动创建菜单项时。

        你可能会将你的菜单项标识符和加速器标识符命名为 IDM_something。) 控件的标识符由控件的创建者确定;回想一下,CreateWindowCreateWindowEx 函数的 hMenu 参数如果你正在创建子窗口,它被视为子窗口标识符。 那就是控件标识符。 (你可以通过调用 GetDlgCtrlID 函数来检索控件的标识符。

        最后,lParam 参数是“如果消息来自控件,则为发送消息的控件的句柄。否则,此参数为 NULL。” 如果通知是由子窗口生成的(显然具有适合该子窗口的通知代码),那么该子窗口句柄将作为 lParam 传递。 如果通知是由加速器或菜单生成的,那么 lParam 是零。

        注意,WM_COMMAND 消息的几乎所有参数一旦你决定了你要生成什么通知,都是强制的。

        如果你正在从控件生成通知,你必须在 wParam 的高字节中传递通知代码,在 wParam 的低字节中传递控件标识符,并将控件句柄作为 lParam 传递。换句话说,一旦你决定 hwndC 窗口想要发送一个 CN_READY 通知,你别无选择,只能这样写:

SendMessage(GetParent(hwndC), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwndC), CN_READY), (LPARAM)hwndC);

        换句话说,所有控件通知都采用以下形式:

SendMessage(GetParent(hwndC), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(hwndC), notificationCode), (LPARAM)hwndC);

        其中 hwndC 是生成通知的控件,notificationCode 是通知代码。 当然,如果你更愿意发布通知而不是发送它,你可以使用 PostMessage 而不是 SendMessage

        其他两种情况(加速器和菜单)通常不是你通常会编码的情况,因为你通常让 TranslateAccelerator 函数处理加速器,让菜单系统处理菜单标识符。 但是,如果出于某种原因,你想假装用户输入了一个加速器或选择了一个菜单项,你可以通过遵循文档中规定的规则手动生成通知。

// 模拟加速器 IDM_WHATEVER 
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_WHATEVER, 1), 0);

        在这里,hwnd 是你想要假装被传递到 TranslateAccelerator 函数的窗口,IDM_WHATEVER 是加速器标识符。

        模拟菜单选择完全相同,只是(根据上述规则),你将 wParam 的高字节设置为零。

// 模拟菜单项 IDM_WHATEVER
SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_WHATEVER, 0), 0);

        在这里,hwnd 是与菜单关联的窗口。 一个窗口可以通过以下方式与菜单关联:通过菜单(通过将菜单句柄传递给 CreateWindowCreateWindowEx 函数显式创建,或者通过在类注册中包含它隐式创建)或通过将菜单显式作为窗口参数传递给像 TrackPopupWindow 这样的函数。

        加速器/菜单情况和控件通知情况之间的一个显著区别是,加速器和菜单标识符由调用应用程序定义,而控件通知由控件定义。

        你可能已经注意到了利用控件通知代码的双关特性的机会。如果一个控件将通知代码定义为零,那么它将“看起来像”菜单项选择,因为在菜单项选择的情况下wParam的高字节是零。

        按钮控件利用了这个双关特性:

#define BN_CLICKED 0

        这意味着,当用户点击按钮控件时,生成的WM_COMMAND消息“闻起来像”菜单选择通知。你可能在没有意识到的情况下在你的对话框程序中利用了这一点。

        静态控件也利用了这个双关特性:

#define STN_CLICKED 0

        但是,为了使静态控件生成 STN_CLICKED 通知,你必须设置 SS_NOTIFY 样式。

        我在开始时说,加速器和菜单情况只是控件情况的特殊情况。 如果你将 WM_COMMAND 消息的各个部分分开,你会发现它们分为两类:

  • 发生了什么?(通知代码。)
  • 发生在谁身上?(控件句柄和ID。)

        在菜单或加速器的情况下,“发生了什么?”是“用户点击了菜单(0)”或“用户输入了加速器(1)”。 “发生在谁身上?”是“这个菜单ID”或“这个加速器ID”。 由于通知不是来自控件,控件句柄是 NULL

       如果这对你们来是显而易见的, 我向 Win32 程序员道歉。

       现在你已经是 WM_COMMAND 消息的专家了,也许你可以解决这个人的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1660398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven的使用

1.第一个Maven工程 1.1 创建约定目录结构 ​ Hello ​ src ​ ——main(存放主程序) ​ ————java(存放源代码文件) ​ ————resources(存放配置文件和资源文件) ​ ——test(存放测试程序) ​ ————java ​ ————resources ​ pom.xml 1.2 创建核心文件 pom.xml …

【Linux】编写一个简易的shell

思维导图 学习目标 将简易的shell代码进行编写。 一、阐述shell的基本思路 在进程程序替换中,我们可以将一个指令交给子进程,让子进程去完成这个指令。如果这个命令是一个内建命令,我们需要将这个命令交给bash进行处理。 大致思路是&#xf…

如何免费获得进仓数据库专家认证(帮你省50块钱)

这篇文章分三个部分 50块钱解决(全靠自己钱可能打水漂考试只有三次机会)50块钱解决(全靠自己考试只有三次机会。)30块钱解决(考试靠我,报名费帮你0元处理,要求只有在线大学生。能力有限只能考K…

【用文本生成歌声】Learn2Sing 2.0——歌声转换算法及梅尔频谱详解

一. 频谱图与梅尔谱图的介绍 频谱图:频谱图可以理解为一堆垂直堆叠在一起的快速傅里叶变换结果。 1.1 信号 在进入频谱图模块之前,首先我们需要了解信号是什么。 信号就是某一特定量随时间变化,对于音频来说,这个特定的变化量就…

马斯克:脑机接口迎来首例植入者,芯片接线发生故障。

马斯克旗下的脑机接口公司Neuralink近日传出关于首例植入者诺兰阿博脑机接口芯片故障的消息。根据Neuralink发布的文章,诺兰阿博的脑机设备发生了故障,多根植入他大脑的接线已经脱落,导致获取数据量减少。目前该公司正在研究导致接线脱落的原…

Taro 快速开始

大家好我是苏麟 , 今天聊聊Trao. 官网 : Taro 介绍 | Taro 文档 (jd.com) 点击快速开始 全局安装 CLI 初始化一个项目 选择配置 : 根据自己需求选择 安装失败先不用管 , 用前端工具打开项目 npm install 安装 , 显示安装失败 怎么解决 ? : 查看报错信息 百度 , 问 AI 工具 运…

HAL PWM 配置 占空比 频率 stm32 学习笔记

title: HALPWM配置占空比频率 tags: STM32ClionHal 1.STM32CubeMX学习笔记(13)——PWM输出(呼吸灯)使用 2.STM32标准库HAL库 | 高精度动态调节PWM输出频率占空比 看你cubemx 里面的配置时钟频率是多少 参照第二篇文章描述修改 下面俩个参数就行 uin…

栈与递归的实现

1. 栈的概念及结构 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。 进行数据插入和删除操作的一端 称为栈顶,另一端称为栈底。 栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则&#x…

数组排序和去重 巨坑!!!紧急避雷

首先&#xff0c;我们要先知道数组的排序和去重操作怎么使用。此处采用C语言。 1.排序操作 #include<iostream> #include <vector> #include<algorithm>using namespace std; int main() {vector<int>arr { 9,1,7,8,6,7,3,6,3 };sort(arr.begin(), a…

加密 加签

加密&#xff1a;一种通过将数据转换成不可读形式的方法&#xff0c;以防止未授权的访问 加签&#xff1a;侧重于验证数据的完整性和来源的真实性&#xff0c;确保数据未被篡改且来源可靠 加密和加签的区别 加密加签目的保护数据的机密性验证数据的完整性和来源的真实性使用方…

windows连接CentOS数据库或Tomcat报错,IP通的,端口正常监听

错误信息 数据库错误&#xff1a; ERROR 2003 (HY000): Cant connect to MySQL server on x.x.x.x (10060) Tomcat访问错误&#xff1a; 响应时间过长 ERR_CONNECTION_TIMED_OUT 基础排查工作 【以下以3306端口为例&#xff0c;对于8080端口来说操作是一样的&#xff0c;只需…

界面组件DevExpress Blazor UI v23.2新版亮点:图表组件全新升级

DevExpress Blazor UI组件使用了C#为Blazor Server和Blazor WebAssembly创建高影响力的用户体验&#xff0c;这个UI自建库提供了一套全面的原生Blazor UI组件&#xff08;包括Pivot Grid、调度程序、图表、数据编辑器和报表等&#xff09;。 DevExpress Blazor控件目前已经升级…

【xxl-job | 第二篇】Windows源码安装xxl-job

文章目录 2.Windows源码安装xxl-Job2.1拉取源码2.2IDEA导入2.3初始数据库数据2.4修改properties配置2.5启动admin并进入任务管理后台2.6jar包运行&#xff08;部署到Linux服务器上&#xff09;2.6.1打包2.6.2在xxl-job-admin打开jar包目录2.6.3cmd运行jar包 2.Windows源码安装x…

【快手秘籍】24小时无人播剧狂赚法门!日干500+的秘密武器,合规安全无顾虑

快手无人播剧&#xff0c;之前很火启面打压了一段时间&#xff0c;最近政策又放松了&#xff0c;因为播电视电影这个板块在快手流量很大。 所以官方又放松了&#xff0c;作为普通人想在快手赚取一份收益&#xff0c;这个赛道最合适了只要花点电费&#xff0c;无其他成本。 快…

网络基础-华为VRP基础CLI操作

基本命令模式 华为设备的命令行模式包括用户视图和特权级模式。 用户视图&#xff08;User View&#xff09;&#xff1a;这是用户登录到华为设备时默认进入的模式。在用户视图下&#xff0c;用户可以执行一些基本的查看命令&#xff0c;但不能进行设备配置或管理。提示符通常…

Flutter笔记:Widgets Easier组件库(13)- 使用底部弹窗

Flutter笔记 Widgets Easier组件库&#xff08;13&#xff09;使用底部弹窗 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this …

设计软件有哪些?渲染软件篇(3),渲染100邀请码1a12

今天我们继续介绍几款渲染软件&#xff0c;方便大家了解 1、渲染100(http://www.xuanran100.com/?ycode1a12) 渲染100是网渲平台&#xff0c;为设计师提供高性能的渲染服务。通过它设计师可以把本地渲染移到云端进行&#xff0c;速度快价格便宜&#xff0c;支持3dmax、vray、…

推荐 6 个超好用的 iterm2 zsh 插件

大家好啊&#xff0c;今天给大家分享几个我日常使用的 iterm2 插件&#xff0c;每一个都很有用&#xff0c;希望能给帮助你提高使用命令行的效率&#xff5e; zsh-autosuggestions 插件地址&#xff1a;https://github.com/zsh-users/zsh-autosuggestions 效果展示 当你输入…

YOLOv9改进策略 | 添加注意力篇 | 利用YOLO-Face提出的SEAM注意力机制优化物体遮挡检测(附代码 + 修改教程)

一、本文介绍 本文给大家带来的改进机制是由YOLO-Face提出能够改善物体遮挡检测的注意力机制SEAM&#xff0c;SEAM&#xff08;Spatially Enhanced Attention Module&#xff09;注意力网络模块旨在补偿被遮挡面部的响应损失&#xff0c;通过增强未遮挡面部的响应来实现这一目…

MySQL表的增删查改【基础部分】

数据表的操作 新增 普通插入 insert into 表名 values(值,值...)注意&#xff1a; 此处的值要和表中的列相匹配 使用’‘单引号或者”“双引号来表示字符串 mysql> insert into student values(123,zhangsan); Query OK, 1 row affected (0.02 sec)指定列插入 insert …