用WM_NCHITTEST消息欺骗Windows(一)
2007-02-02 14:26

通常,我们拖动对话框窗口的标题栏来移动窗口,但有时候,我们想通过鼠标在客户区上拖动来移动窗口。

一个容易想到的方案是,处理鼠标消息WM_LBUTTONDOWN和WM_LBUTTONUP。在OnLButtonUp函数中计算鼠标位置的变化,调用MoveWindow实现窗口的移动。

注意,拖动标题栏移动窗口的时候,会出现一个矩形框,它提示了窗口移动的当前位置。当鼠标左键放开的时候,窗口就移动到矩形框所在位置。而我们的实现方案中没有这个功能。

要实现此功能,我们必须自己来画这些矩形。

事实上,我们没有必要自己来做这件事情,因为Windows已经给我们做好了。

试想,如果我能够欺骗Windows,告诉它现在鼠标正在拖动的是标题栏而不是客户区,那么窗口移动操作就由Windows来代劳了。

要欺骗Windows并不像想像中的困难,甚至非常简单。

我们利用一个消息:WM_NCHITTEST。

MSDN对它的解释是:

The WM_NCHITTEST message is sent to a window when the cursor moves, or when a mouse button is pressed or released. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.

这个消息是当鼠标移动或者有鼠标键按下时候发出的。

Windows用这个消息来做什么? “HITTEST”就是“命中测试”的意思,WM_NCHITTEST消息用来获取鼠标当前命中的位置。

WM_NCHITTEST的消息响应函数会根据鼠标当前的坐标来判断鼠标命中了窗口的哪个部位,消息响应函数的返回值指出了部位,例如它可能会返回HTCAPTION,或者HTCLIENT等。(其返回值有很多,请查阅MSDN)。

为了便于理解,我先描述一下Windows对鼠标键按下的响应流程:

1.  确定鼠标键点击的是哪个窗口。Windows会用表记录当前屏幕上各个窗口的区域坐标,当鼠标驱动程序通知Windows鼠标键按下了,Windows根据鼠标的坐标确定它点击的是哪个窗口。

2.  确定鼠标键点击的是窗口的哪个部位。Windows会向鼠标键点击的窗口发送WM_NCHITTEST消息,来询问鼠标键点击的是窗口的哪个部位。(WM_NCHITTEST的消息响应函数的返回值会通知Windows)。通常来说,WM_NCHITTEST消息是系统来处理的,用户一般不会主动去处理它(也就是说,WM_NCHITTEST的消息响应函数通常采用的是Windows默认的处理函数)。

3.  根据鼠标键点击的部位给窗口发送相应的消息。例如:如果WM_NCHITTEST的消息响应函数的返回值是HTCLIENT,表示鼠标点击的是客户区,则Windows会向窗口发送WM_LBUTTONDOWN消息;如果WM_NCHITTEST的消息响应函数的返回值不是HTCLIENT(可能是HTCAPTION、HTCLOSE、HTMAXBUTTON等),即鼠标点击的是非客户区,Windows就会向窗口发送WM_NCLBUTTONDOWN消息。

我们有必要详细讨论一下:如果WM_NCHITTEST的消息响应函数的返回值是HTCAPTION,即指示了鼠标点击了标题栏,接下去Windows的处理是怎样的?

上面已经提到,接下来,Windows会向窗口发送WM_NCLBUTTONDOWN消息。

MSDN对WM_NCLBUTTONDOWN消息描述如下:

WM_NCLBUTTONDOWN

nHittest = (INT) wParam;    // hit-test value

pts = MAKEPOINTS(lParam);   // position of cursor

WM_NCLBUTTONDOWN的wParam指示了鼠标点击的窗口部位,lParam指示了当前鼠标的坐标。

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

系统默认处理又是怎样的呢?系统发现wParam指示了鼠标点击的是标题栏,就会标识当前窗口处于“拖拽状态”(Windows内部记录了每个窗口的状态信息)。由于标识了“拖拽状态”,则从此刻起到鼠标键放开之前,你的鼠标移动状况完全由Windows跟踪。它根据鼠标的移动,使得窗口作“同步”移动。

注意,这个过程中,窗口不会收到WM_NCMOUSEMOVE消息,因为窗口和鼠标是“同步”移动的,你的鼠标相对于窗口是静止的。(这些细节你可以自己写个示例来测试并分析得出,事实上我也是这么做的。如果我的观点有错误,欢迎指正)。

WM_NCHITTEST消息欺骗Windows(一)相关推荐

  1. WM_NCHITTEST消息

    用WM_NCHITTEST消息欺骗Windows(一) 2007-02-02 14:26 通常,我们拖动对话框窗口的标题栏来移动窗口,但有时候,我们想通过鼠标在客户区上拖动来移动窗口. 一个容易想到的 ...

  2. 关于WM_NCHITTEST消息(移动无标题对话框多个)

    我为了移动一个无标题栏的窗体,使用了WM_NCHITTEST消息,这个消息大概如下: 通常,我们拖动对话框窗口的标题栏来移动窗口,但有时候,我们想通过鼠标在客户区上拖动来移动窗口. 一个容易想到的方案 ...

  3. [转]关于WM_NCHITTEST消息

    http://www.cnblogs.com/GnagWang/archive/2010/09/12/1824394.html 我为了移动一个无标题栏的窗体,使用了WM_NCHITTEST消息,这个消 ...

  4. 关于WM_NCHITTEST消息

    通常,我们拖动对话框窗口的标题栏来移动窗口,但有时候,我们想通过鼠标在客户区上拖动来移动窗口. 在OnLButtonDown中添加代码如下代码也可以完成窗体拖动: ::PostMessage(m_hW ...

  5. 取代Win10 消息称Windows 10X将在明年推出

    本月,微软发布Surface的新品(全新配置Surface Pro X.全新的Surface Laptop Go)后,偷偷做了一个小调整,直接从官网上删除了Surface Neo字样,这也意味着这款产 ...

  6. Windows程序的窗口和消息 -- 一个Windows程序从生到死

    注:以下内容为学习笔记,多数是从书本.资料中得来,只为加深印象,及日后参考.然而本人表达能力较差,写的不好.因非翻译.非转载,只好选原创,但多数乃摘抄,实为惭愧.但若能帮助一二访客,幸甚! 1.一个完 ...

  7. 重磅消息!微信Windows电脑版本,终于支持刷朋友圈啦!

    苹果系统电脑微信macOS版3.0.0正式版,早在今年3月份左右就已经新增了微信朋友圈功能,Windows系统用户近期终于等来了PC版微信v3.3版本,这次微信更新新增了PC版朋友圈功能,还包括点赞. ...

  8. VC++ 鼠标非显示区域命中测试消息WM_NCHITTEST和相关编程问题学习1

    此消息代表非显示区域命中测试:非显示区域,应该指窗口客户区以外的区域: 这个消息优先于所有其他的显示区域和非显示区域鼠标消息:其中lParam参数含有鼠标位置的x和y屏幕坐标,wParam 这里没有用 ...

  9. windows 编程 —— 消息与参数(滚动条、键盘、鼠标)

    目录: 滚动条 键盘 鼠标 滚动条ScrollBar 发送消息:WM_VSCROLL和WM_HSCROLL 参数wParam:wParam消息参数被分为一个低字组和一个高字组.wParam的低字组是一 ...

最新文章

  1. 红帽集群套件RHCS
  2. 4n35光耦引脚图_在选择光耦继电器的过程中需要注意哪些问题?-先进光半导体...
  3. Android开发之判断APP前后台的方法
  4. 人工智能泰斗迈克尔·乔丹分享机器学习要义:创新视角,直面挑战
  5. javascript的浏览器Bom详解,window、location、history对象
  6. 【课题总结】OpenCV 抠图项目实战(3)抠图综述
  7. 贝叶斯优化优化参数,以Kmeans为例
  8. 使用requests库实现多线程下载
  9. 删除一个空目录的JAVA代码
  10. IOMMU之Interrupt Remapping
  11. 使用media player和foobar的DLAN服务
  12. 卓有成效的管理者—第七章 有效的决定
  13. 电商后台管理系统项目 一
  14. 计算机两万字符英语文献翻译,自动化专业相关英文文献加翻译(20000字符).doc
  15. 基于STM32控制的PS2摇柄模块—双轴按键摇杆控制器控制TFTLCD
  16. 航空公司客户流失分析
  17. python给矩阵赋值_python – 基本Numpy数组值赋值
  18. 投资学实务 期货日志及实践总结
  19. htb_Escape (mssql渗透,winrm)
  20. Google GMS(CTS, GTS,CTSVerifier)

热门文章

  1. 月历1997年php代码_PHP实现的简单日历代码
  2. 台积电将重新代工高通骁龙875处理器 5nm工艺
  3. AUTOSAR基础篇之OS(上)
  4. 【Android】Android.bp 实例之源码编译动态库
  5. Qt编写地图综合应用42-离线轮廓图
  6. C语言初学者复刻经典扫雷小游戏(图形界面,非黑白窗口)(含源码)
  7. 塞班系统走向消亡:细数塞班的发展简史
  8. houdini入门藤曼笔记
  9. 从易经中看软件开发之道
  10. Unity中使用WebSocket