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. linux shell编程指南第二十章------向脚本传递参数

    前面已经讲到如何使用特定变量$ 1 . . $ 9向脚本传递参数.$ #用于统计传递参数的个数.可 以创建一个u s a g e语句,需要时可通知用户怎样以适当的调用参数调用脚本或函数. 简单地说,下 ...

  2. WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer)

    原文:WCF技术剖析之十二:数据契约(Data Contract)和数据契约序列化器(DataContractSerializer) [爱心链接:拯救一个25岁身患急性白血病的女孩[内有苏州电视台经济 ...

  3. Project configuration is not up-to-date with pom.xml错误解决方法

    导入一个Maven项目之后发现有一个如下的错误: Project configuration is not up-to-date with pom.xml. Run project configura ...

  4. cocos2d-x游戏开发系列教程-坦克大战游戏之虚拟手柄控制坦克移动

    上篇显示了控制手柄,但是还不能用来控制坦克, 这篇将会讲手柄和坦克的移动结合起来. 1.先在CityScene场景中实现场景的虚函数virtual void onEnter(); onEnter在进入 ...

  5. Qt4----子例化QDialog(可扩展对话框的使用)

    1.linux下安装Qt4请参考如下博文: Qt4在linux下的安装 2.Qt4工程的创建请参考如下博文: Qt4创建工程的几种方法:linux系统 3.可扩展对话框 通过纯代码的形式,建立工程.点 ...

  6. 聊天气泡的绘制(圆角矩形+三角形+黑色边框,关键学会QPainter的draw函数就行了),注意每个QLabel都有自己的独立坐标

    头文件: #ifndef GLABEL_H #define GLABEL_H #include <QLabel> #include <QPainter> #include &l ...

  7. PHP学习之-1.5 字符串

    字符串 一个字符串是用双引号扩起来的一个词或者一个句子,比如 "Hello Word" ,你可以使用PHP语言输入这个字符串,像这样 <?php echo "Hel ...

  8. 程序中非action获得spring容器

    java类: public class MySpringContext implements ApplicationContextAware{ private static ApplicationCo ...

  9. 九度OnlineJudge之1018:统计同成绩学生人数

    题目描述: 读入N名学生的成绩,将获得某一给定分数的学生人数输出. 输入:                        测试输入包含若干测试用例,每个测试用例的格式为 第1行:N 第2行:N名学生的 ...

  10. python学习教程(九)sqlalchemy框架的modern映射

    首先写一个modern.py文件, from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Col ...