原文地址:https://blog.csdn.net/whm243149796/article/details/78966065

当用户点击菜单、按钮、下拉列表框等控件时候,会触发WM_COMMAND

LOWORD(wParam) 是控件或菜单或加速键的ID,菜单的sparator的ID为0

如果LOWORD(wParam) 是控件ID,HIWORD(wParam)是notification code, 比如BN_CLICKED, BN_DBLCLK等,标志用户对控件的操作,双击,单击之类。

如果LOWORD(wParam) 是菜单ID,HIWORD(wParam)是0。

如果LOWORD(wParam) 是加速符ID,HIWORD(wParam)是1。

如果LOWORD(wParam) 是控件ID,lParam是控件的句柄值,否则为NULL。其实,GetDlgItem(hWnd, LOWORD(wParam)) == lParam。

Notification Code的命名规律:

列表框:   LBN_*****

组合框:   CBN_****

Tab框:    TBN_****

按钮:     BN_*****

Edit :        EN_*****

对于WM_SYSCOMMAND 中如果是系统菜单的消息,都必须要交给DefWindowProc 来处理,并且将返回值返回给Windows ,不然你会发现不能拖动窗体、改变大小、最大最小化操作等。因为你如果不交给DefWindowProc 处理,相当于屏蔽了SC_RESTORE、SC_MOVE、SC_MAXIMIZE、SC_MINIMIZE、SC_CLOSE 等等操作了。这些命令都是通过Windows 投递WM_SYSCOMMAND 消息,在DefWindowProc 中进行处理的。

WM_COMMAND产生的条件:点击菜单,点击加速键,点击子窗口按钮,点击工具栏按钮。这些时候都有command消息产生。

WM_COMMAND消息中有两个参数,wparam、lparam,定义如下:

wParam 高两个字节 通知码

wParam 低两字节 命令ID

lParam 发送命令消息的子窗体句柄。

对于菜单和加速键来说,lParam为0,只有控件此项才非0。命令ID也就是资源脚本中定义的菜单项的命令ID或者加速键的命令ID;菜单的通知码为0;加速键的通知码为1。

对于Windows菜单中菜单项和加速键,点击后,Windows会向所属的窗体发送WM_SYSCOMMAND,而不是WM_COMMAND消息。注意,WINDOWS菜单是系统菜单,也就是在标题栏点击鼠标左键的时候弹出的菜单。我们可以捕获WM_CREATE消息,加入自己的操作:GetSysMenu获取系统菜单句柄,然后对系统菜单进行操作,并且捕获添加菜单项(根据菜单命令ID)ID对应的WM_SYSCOMMAND消息进行处理。修改系统默认的菜单行为。

子窗体和父窗体:

子窗体被触发时,向父窗体发送一个WM_COMMAND消息,父窗体的窗口函数处理这个消息,进行相关的处理。lParam表示子窗口句柄,LOWORD(wParam)表示子窗口ID,HIWORD (wParam)表示通知码(例如单击,双击,SETFOCUS等)。

WM_MESSAGE、WM_COMMAND、WM_NOTIFY等消息有什么不同?

WM_MESSAGE是最普通的WINDOWS消息,对于这种类型的消息没什么好说的。那WM_COMMAND和WM_NOTIFY消息都是WINDOWS CONTROL给它的父窗体发的消息,那这两种消息有什么不同呢?WM_COMMAND消息其实是早期的(WIN3.X时代)子窗体消息,子窗体给父窗体发送消息,父窗体就捕获WM_COMMAND来处理子窗体的消息。但是这个消息只包括了有限的信息,例如wParam包括了子窗口ID和通知码,lParam则包括了子窗口句柄,就这点信息了,如果想知道一些额外的信息的话(例如,鼠标点在了子控件的位置)就要借助于其他的WM_*消息。所以对于新型的WIN32控件,微软就增加了一个新的NOTIFICATION消息,这个消息的参数是这样的:wParam包含了控件ID,而lParam则包含了一个结构体的指针,这个结构体是NMHDR结构或者以NMHDR结构为第一项的一个更大的结构体。这样就可以包含了很多的子控件想给父窗体提供的信息了,甚至可以自己去定义这种的结构体。
    这就是这几种消息的差别点了。

控件的自画:
    首先在创建控件的时候当然就是指定BS_OWNERDRAW的STYLE,这个STYLE是告诉控件,别自己处理外观,让主程序来处理你的外观,这时你就有权决定这个控件是画成什么样子了。然后就是处理WM_DRAWITEM的消息,利用 LPDRAWITEMSTRUCT pdis = (LPDRAWITEMSTRUCT) lParam; 来取得一些必要的信息,如按钮的DC,位置等。这才能对这个DC的内容进行绘画啊。COMMON CTRL的STYLE都在COMMCTRL.H头文件里。

按钮在以下状态时会对它的父窗口发送WM_COMMAND的消息:
按了一次(BN_CLICKED),取得焦点(BN_SETFOCUS),失去焦点(BN_KILLFOCUS)等。
这个是按钮的发送WM_COMMAND的条件,其他的控件什么时候会发送WM_COMMAND消息可查看该控件的通知码(在wParam的高位HIWORD)。例如,滚动条控件在被滚动的时候会向它的父窗体发送消息,但是不是WM_COMMAND消息,而是WM_VSCROLL和WM_HSCROLL消息。这只是为了说明凡是子控件,都会在适当的条件下向它的父窗体发送消息。无论是WM_COMMAND还是WM_NOTIFY或是WM_VSCROLL消息等。MoveWindow会产生WM_SIZE消息。

在Windows3.1里,控件会将mouse, keybord等等的消息通知它的父窗口, 使用的消息就只有WM_COMMAND, 事件种类和控件ID被包含在wParam中, 控件的句柄包含在lParam中。由于wParam和 lParam已经满了,当控件要向父窗口发送其它特殊消息同时附带很多信息的时候就没有地方可以存放它们了。所以Windows3.1中定义了许多其它的消息种类,比如WM_VSCROLL, WM_CTLCOLOR等等,每种消息wParam,lParam中附带的信息是不同的。 
      当到了Win32后,控件的种类越来越多,当然不可以为每一个控件都定义一套消息,这样也不利于系统的扩充。所以在Win32中定义了唯一一个强大的消息 WM_NOTIFY。当然WM_NOTIFY也遵守原来的消息规则,既只带参数wParam和lParam。唯一不同处在于,此时的lParam中传送的是一个NMHDR指针。不同的控件可以按照规则对NMHDR进行扩充,因此WM_NOTIFY消息传送的信息量可以相当的大,这个可以看看MSDN中的相关说明,TreeControl中就有很多这种消息。 
    
现在就可以知道为什么有ON_MESSAGE ,ON_COMMAND, , ON_NOTIFY了。 
ON_MESSAGE是处理所有的Windows的消息的,因为所有的消息都以相同的格式传送,也就是ID, WPARAM, LPARAM. 
ON_COMMAND是专门处理WM_COMMAND消息的,这样我们就不用自己解开WM_COMMAND中wParam和lParam中传送的控件ID, 事件种类…,所有的都在MFC内部解决了:),当然方便了。 
ON_NOTIFY更是不用说了,看看他的处理函数,是不是把NMHDR解出来了。 
    
这样一样就一目了然了,ON_COMMAND和ON_NOTIFY都可以用ON_MESSAGE来处理,只不过自己要多做很多事情。ON_COMMAND和ON_NOTIFY最好就不要互换了!

WM_COMMAND消息的更多相关文章

  1. 【转】Windows消息投递流程:WM_COMMAND消息流程

    原文网址:http://blog.csdn.net/hyhnoproblem/article/details/6182585 该示例通过研究基本的单文档程序的“文件”--“打开”命令,分析WM_COM ...

  2. SendMessage发送WM_COMMAND消息控制另一个程序的某一个按钮

    procedure TfrmMain.btnSendClick(Sender: TObject); var hCalc, h1: Cardinal; begin WinExec('calc', SW_ ...

  3. windows消息机制详解(转载)

    消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了.例如,单击鼠标.改变窗口尺寸.按下键盘上的一个键都会使Windows发送一个消息给应用程序.消息本身是作为一个记录传递给应用程序的 ...

  4. windows消息机制(MFC)

    消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据 ...

  5. Windows 消息机制

    Windows 是一个消息驱动的操作系统.一个消息由一个消息名称(UINT 类型)和两个参数(WPARAM,LPARAM)构成.当用户进行了输入或是窗口的状态发生改变时,系统会发送消息到某一个窗口.例 ...

  6. WM_INITDIALOG与WM_CREATE消息的区别

      WM_CREATE是所有窗口都能响应的消息,表明本窗口已经创建完毕(可以安全的使用这个窗口了,例如在它上面画控件等).在响应WM_CREATE消息响应函数的时候,对话框及子控件还未创建完成,亦是说 ...

  7. Windows 消息机制详解

    总的来说: MSG包括: 窗口句柄,指示MSG发送的目的窗口 消息标识 lPARAM.wParam 发送时间 发送时的鼠标位置   关于消息队列: Windows系统有一个系统消息队列 每个线程都有一 ...

  8. MFC程序中消息以及函数的处理顺序简介[转]

    MFC应用程序中处理消息的顺序 1.AfxWndProc()      该函数负责接收消息,找到消息所属的CWnd对象,然后调用AfxCallWndProc 2.AfxCallWndProc()  该 ...

  9. CN消息的来源——父窗口不知道怎么处理,于是把这个消息加上CN_BASE在分发到实际的子窗体

    VCL存在一些非API消息以供其内部使用,为什么要这样做呢?这要从WM_COMMAND & WM_NOTIFY消息说起,我们说WM_COMMAND消息并不是直接发给实际产生消息的窗体,而是发送 ...

随机推荐

  1. Linux拉你入门

    前言:为了做一个更优秀的程序猿,Linux是必不可少的,因此利用闲杂的时间来增加自己对Linux的认识 (一)关于Linux命令编(至于怎样安装vmvare这一个章节就先不介绍了) 1.基础命令 1. ...

  2. Web 学习笔记(一)百度统计

    一.百度统计是什么? 百度统计是百度推出的一款免费的专业网站流量分析工具,能够告诉用户访客是如何找到并浏览用户的网站,在网站上做了些什么,有了这些信息,可以帮助用户改善访客在用户的网站上的使用体验,不 ...

  3. 判断闰年(Java)

    package day01; import java.util.Scanner; public class leap_year { public static void main (String[] ...

  4. 【LDAP】LDAP注入漏洞与防御

    0x01 前言 前两天爆了一个LDAP漏洞,据说存在了8年现在才被发现,感概一下,不知这8年来有多少站被搞了... 想着复现这个漏洞,就先复习一下LDAP注入的相关知识吧,差了很多资料,记一下笔记. ...

  5. 利用openpyxl模块来操作Excel

    python 读写 excel 有好多选择,但是,方便操作的库不多,在我尝试了几个库之后,我觉得两个比较方便的库分别是 xlrd/xlwt.openpyxl. 之所以推荐两个库是因为这两个库分别操作的 ...

  6. luogu P3250 [HNOI2016]网络

    传送门 考虑只有一个询问,怎么使用暴力枚举最快的得到答案.因为要求最大的,所以可以把链按权值从大往小排序,然后往后扫,找到一个没有交的就是答案,直接退出 一堆询问,可以考虑整体二分,先二分一个值\(m ...

  7. Java Map在遍历过程中删除元素

    Java中的Map如果在遍历过程中要删除元素,除非通过迭代器自己的remove()方法,否则就会导致抛出ConcurrentModificationException异常.JDK文档中是这么描述的: ...

  8. 安装UEStudio以及破解

    1.下载UEStudio以及注册机 百度网盘地址:链接:http://pan.baidu.com/s/1hrJfxx6 密码:td1b 如图:第一个是注册机,第二个是UEStudio 2.安装UESt ...

  9. 自动化测试平台的搭建--Jenkins

    1.下载:进入官网https://jenkins.io/download/,直接下载war包(约70M): 2.将下载好的war包直接放入到tomcat/webapp下: 3.进入bin目录下启动服务 ...

  10. ionic 照相机 Camera

    1.官网: https://ionicframework.com/docs/native/camera/#DestinationType 2.引入插件 $ ionic cordova plugin a ...