我竟是小丑

问题描述

表象

拾取元素时出现“穿透”,经过 WindowsAPI 拾取目标控件元素信息时,鼠标拾取元素的同时还执行了目标控件上的操做,这种状况是不容许的。(PS:经过单击进行拾取,常规状况下已作了屏蔽,不会执行目标控件的操做)ide

里象

通过分析和测试,得出结论。误操做的控件绑定的不是 Click事件 而是 MouseUp事件测试

分析屏蔽操做漏洞

分析屏蔽操做

在正确捕获到目标元素后会取消 CallNextHookEx事件 的执行,从而达到单击时屏蔽目标控件操做的目的。优化

分析捕获操做

目的是为了捕获“单击操做”,但 WindowsApi 只有 MouseDown 和 MouseUp事件。因而将两次都算做单击事件,并作了些许优化。即两次事件的间隔时间小于200ms则第二次事件执行时直接 return。spa

分析目标控件执行缘由

对于绑定了 Click事件 的控件在第二次捕获操做后直接return, CallNextHookEx 检测不到完整的Click操做直接等于屏蔽效果。
对于绑定了 MouseUp事件 的控件在第二次捕获后直接return, CallNextHookEx 恰好能够检测到MouseUp事件就继续执行。
顺着此思路,第二次捕获后 return 时取消 CallNextHookEx事件 便可。设计

小插曲

以为别人的想法有点“多此一举”,毕竟先捕获两次在屏蔽一次还出了问题,就想进行优化。换一种思路,若尝试只捕获一次,是否就不存在此问题?code

第一次尝试理解出错,捕获了 MouseDown事件,觉得会屏蔽 MouseUp事件。结果没捕获 MouseUp事件 致使目标控件的 MouseUp事件 直接执行了。
反过来捕获 MouseUp 就能够了。blog

为何说我是小丑呢?

一开始以为我这种写法还挺好,结果存在巨大的漏洞,即目标控件绑定了MouseDown事件我这种方式又会出现“穿透”。别人的写法虽然冗余但不存在此问题。事件

其余

初学时还有另外一种想法:即都不执行 CallNextHookEx 事件会怎样,结果鼠标移动事件都没法触发,致使鼠标没法移动class

单一捕获判断条件

 if (wParam == WM_LBUTTONDOWN)
 if (wParam == WM_LBUTTONUP)
鼠标移动512 ox200
鼠标按下513 0x201
鼠标弹起514 0x202
WM_LBUTTONDOWN 鼠标按下
WM_LBUTTONUP 鼠标弹起
捕获条件

捕获

 MouseHookProc(int nCode, int wParam, IntPtr lParam) sed

CallNextHookEx 

 int CallNextHookEx( int idHook, int nCode, int wParam, IntPtr lParam) 

测试过程

测试用例:建立一个含三种事件的Java应用和C#应用(问题暴露在一个Java应用上,日常处理Windows平台的应用较多)

  • 推测一:两种应用分别来测试,究竟与平台是否相关联。经过测试发现与平台关联性不大
  • 推测二:是否和Web端的事件冒泡相似。经过一些测试发现两者并不想通
  • 推测三:控件注册的事件不同,经过按住鼠标不放,可以捕获且不触发事件,大体推测与绑定的事件相关
  • 推测四:我点在了哪里?应用仍是遮盖层,程序本来设计的有遮盖层,算是干扰项。经过质询同事了解到咱们并无点在遮盖层上。

因为一开始不知道系统是如何屏蔽原目标控件事件的,给问题分析带来很大的难度

相关文章
相关标签/搜索