1,回调函数工作机制

回调函数由操作系统自动调用,回调函数的返回值当然也是返回给操作系统了。

2,截获操作系统发出的消息,截获到后,将另外一个消息返回给操作系统,已达到欺骗操作系统的目的。

下面还是以具体例子来说明比较好。

在 Windows下,每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息。通常情况下,要把这个消息直接交给 DefWindowProc 函数处理,该函数会返回一个值来告诉 Windows 鼠标按下的是窗口的哪一部分。Windows 利用这个返回值来决定要发送的鼠标消息的类型。例如,如果用鼠标左键单击窗口的标题栏,处理WM_NCHITTEST 消息的 DefWindowProc 函数会返回 HTCAPTION,然后 Windows 会再向该
窗口发送 WM_NCLBUTTONDOWN 消息。如果 DefWindowProc 的返回值是 HTCLIENT,Windows 就将鼠标所在位置的坐标从屏幕坐标转化成为客户区坐标,并且通过WM_LBUTTONDOWN 消息通知用户。

3,既然谈到了截获消息,势必要谈下由“消息产生消息”了,同样以例子来说明:

Windows用WM_NCHITTEST消息产生所有其它鼠标消息,这种由消息引出其它消息的想法在Windows中是很普遍的。举个例子,如果您在一个Windows程序的系统菜单图标上双击一下,那么程序将会终止。双击产生一系列的WM_NCHITTEST消息。由于鼠标定位在系统菜单图标上,因此DefWindowProc将传回HTSYSMENU的值,并且Windows把wParam等于HTSYSMENU的WM_NCLBUTTONDBLCLK消息放在消息队列中,也就是说WM_NCLBUTTONDBLCLK消息的wParam参数是HTSYSMENU,这个是由DefWindowProc返回的。 窗口消息处理程序通常把鼠标消息传递给DefWindowProc,当DefWindowProc接收到wParam参数等于HTSYSMENU的WM_NCLBUTTONDBLCLK消息时,它就把wParam参数等于SC_CLOSE的WM_SYSCOMMAND消息放入消息队列中(这个WM_SYSCOMMAND消息是在使用者从系统菜单中选择「Close」时产生的)。同样地,窗口消息处理程序也把这个消息传给DefWindowProc。DefWindowProc通过给窗口消息处理程序发送WM_CLOSE消息来处理该消息。

下面再以拖动窗口为例来说明:

单击鼠标,系统投递WM_NCHITTEST到消息队列,lParam参数记录了光标的移动目的位置,由DefWindowProc处理,该函数的返回值代表当前鼠标移动到了窗口的哪个部位,如HTCLIENT,HTCAPTION,由DefWindowProc处理WM_NCHITTEST,将控制权返回给系统。DefWindowProc返回HTCAPTION,此时操作系统返回什么消息呢?应该是WM_NCLBUTTON,其wParam参数包含了鼠标在窗口的哪个部位,lParam包含了鼠标的坐标位置。

如果应用程序没有对该消息响应,则由系统默认处理。

系统默认处理又是怎样的呢?系统发现wParam指示了鼠标点击的是标题栏,就会标识当前窗口处于“拖拽状态”(Windows内部记录了每个窗口的状态信息)。由于标识了“拖拽状态”,则从此刻起到鼠标键放开之前,你的鼠标移动状况完全由Windows跟踪。它根据鼠标的移动,使得窗口作“同步”移动。注意,这个过程中,窗口不会收到WM_NCMOUSEMOVE消息,因为窗口和鼠标是“同步”移动的,你的鼠标相对于窗口是静止的。(这些细节你可以自己写个示例来测试并分析得出,事实上我也是这么做的。如果我的观点有错误,欢迎指正)。

当放开鼠标左键时,系统产生WM_NCHITTEST消息,lParam包含当前坐标,该消息由DefWindowProcl处理,处理完成后,由DefWindowProc投递WM_NCLBUTTONUP消息,wParam参数表示当前光标所在窗口的部位,它是由DefWindowProc返回的,lParam代表光标的坐标。当然了这个消息同样由DefWindowProc来处理,处理完毕后,这个函数同时需要发出WM_SYSCOMMAND消息,它的wParam应该是SC_MOVE,代表窗口移动,该消息同样由DefWindowProc处理,处理完后,它在发出WM_MOVE消息,lParam代表了窗口左上角的坐标....先分析到这....

下面对上面的描述进行总结:

当光标移动或者鼠标按下或者释放时,系统产生WM_NCHITTEST消息,其中wParam为空,lParam参数记录了光标的x和y坐标。该消息由DefWindowProc处理,在合适的情况下(多数情况下其实都是这样),DefWindowProc又会向消息队列投递一个WM_SYSCOMMAND消息(注:当用户点击菜单命令时,发出这个消息),其wParam参数反应了用户单击了哪个菜单项命令。回调函数把这个消息给DefWindowProc处理,这个函数再投递一个WM_CLOSE(如果用户选择的是菜单的close命令)给用户程序消息队列。

//下面分析移动鼠标

4,鼠标消息,WM_NCHITTEST,WM_MOUSEMOVE,WM_NCMOUSEMOVE

如果鼠标在窗口移动,系统投递WM_NCHITTEST到消息队列,lParam参数记录了光标的移动目的位置,由DefWindowProc处理,该函数的返回值代表当前鼠标移动到了窗口的哪个部位,如HTCLIENT,HTCAPTION,将控制权返回给系统。

假设光标在标题栏,此时系统会投递一个WM_NCMOUSEMOVE到消息队列,wParam是上面DefWindowProc的返回值,代表了光标移动到了窗口的哪个部位,lParam代表了当前光标所在的坐标。

http://blog.sina.com.cn/s/blog_673ef8130100mw4b.html

深刻:截获windows的消息并分析实例(DefWindowProc),以WM_NCHITTEST举例(Windows下每一个鼠标消息都是由 WM_NCHITTEST 消息产生的,这个消息的参数包含了鼠标位置的信息)的更多相关文章

  1. Kafka 和 ZooKeeper 的分布式消息队列分析

    1. Kafka 总体架构 基于 Kafka-ZooKeeper 的分布式消息队列系统总体架构如下: 如上图所示,一个典型的 Kafka 体系架构包括若干 Producer(消息生产者),若干 bro ...

  2. 【NX二次开发】分析曲线某位置的信息 UF_MODL_ask_curve_props

    分析曲线某位置的信息:点.切线.主副法线.半径等 extern DllExport void ufsta(char *param, int *returnCode, int rlen) { UF_in ...

  3. windows消息机制与实例

    windows发送窗口消息 所需工具:spy++,visual studio 2017,c#语言 技术路线:首先通过spy++获得所要操纵的窗口的句柄,函数的原型声明为: [DllImport(&qu ...

  4. windows XP系统内核文件分析(全)

    Windows XP个别 System32 文件 System32 文件夹下个别要移除的文件 我们就要删除另外600 个 system32 文件...我们要一次把它们全都解决掉. 以下是我所删除的 S ...

  5. 如何利用wireshark对TCP消息进行分析

    原文:https://www.cnblogs.com/studyofadeerlet/p/7485298.html 如何利用wireshark对TCP消息进行分析   (1) 几个概念介绍 1 seq ...

  6. Qt 事件系统浅析 (用 Windows API 描述,分析了QCoreApplication::exec()和QEventLoop::exec的源码)(比起新号槽,事件机制是更高级的抽象,拥有更多特性,比如 accept/ignore,filter,还是实现状态机等高级 API 的基础)

    事件系统在 Qt 中扮演了十分重要的角色,不仅 GUI 的方方面面需要使用到事件系统,Signals/Slots 技术也离不开事件系统(多线程间).我们本文中暂且不描述 GUI 中的一些特殊情况,来说 ...

  7. ANR问题分析实例

    ANR监测机制包含三种: Service ANR,前台进程中Service生命周期不能超过20秒,后台进程中Service的生命周期不能超过200秒. 在启动Service时,抛出定时消息SERVIC ...

  8. 窗口、消息查看分析利器Spy++

    Spy++ —— 窗口.消息查看分析利器 Spy++ —— 窗口.消息查看分析利器 2016年07月15日 00:25:22 阅读数:23170 1,简介   Microsoft Spy++是一个非常 ...

  9. [转]C#截获本机数据包方法实例

    本文向大家介绍Windows Sockets的一些关于用C#实现的原始套接字(Raw Socket)的编程,以及在此基础上实现的网络封包监视技术.同Winsock1相比,Winsock2最明显的就是支 ...

随机推荐

  1. 严重: Servlet.service() for servlet jsp threw exception java.lang.IllegalStateException: getOutputStream() has already been called

    错误: 严重: Servlet.service() for servlet jsp threw exception java.lang.IllegalStateException: getOutput ...

  2. pomelo研究笔记-RPCclient

    1. mailbox数据收发模块 一个RPC客户端可能同一时候须要调用多个远端(server)提供的服务.在pomelo里每一个server抽象为一个mailbox.先来看看mailbox的实现: v ...

  3. ios9 之后 配置百度地图出现的错误

    链接地址:http://blog.csdn.net/u011303663/article/details/48596315 错误 ld: '/Users/xxx/Documents/xxx/Baidu ...

  4. 利用T4模版生成EF实体

    直接上代码,只需要修改EF实体的地址就可以了. <#@ template language="C#" debug="false" hostspecific ...

  5. linux学习之四---gdb调试

    在Linux应用程序开发中,最经常使用的调试器是gdb. 一.启动和退出gdb gdb调试的对象是可运行文件,而不是程序的源码.假设要使一个可运行文件能够被gdb调试,那么使用编译器gcc编译时须要增 ...

  6. EasyUI - ComboBox 下拉组件

    效果: html代码: <input id ="comb" name ="comb"/> JS代码: $(function () { $('#com ...

  7. Eclipse用法和技巧十:显示代码outline

    在一个文件中快速找到某一个方法或者某一个作用域,可以使用 Ctrl+O或者Ctrl+F3,快速显示当前代码的outline,进行快速查找.效果如下:        这里主要是补充一些后续操作,能更加方 ...

  8. javascript 学习资料网址一览

    1.http://www.runoob.com/ 2.https://developer.mozilla.org/zh-CN/ 3.http://www.imooc.com/   视频类

  9. Android程序检测网络是否可用

    在做Android应用程序中,连接网络的时候,常常要用到检测网络状态是否可用,在这里分享一个比较好用的方法. 本人参考:http://blog.csdn.net/sunboy_2050/article ...

  10. Head First PHP &amp;MySQL学习笔记

      近期一段时间在学习PHP,买了<Head First PHP&MySQL>中文版这本书,之前买过<Head First设计模式>,感觉这系列的书籍整体来说非常不错. ...