本文以windows平台为例,使用常规实时获取目标窗口可见区域的方法存在着枚举桌面窗口比较耗时和比较消耗机器性能以及很难获取窗口之间层叠上下层次关系等弊端而导致获取目标窗口可见区域存在低效的问题。
(图一)
以图一为例,假设窗口1的RECT为Rect1,窗口2的RECT为Rect2,窗口3的RECT为Rect3。那么窗口1的可见区域(Region)就是Rect1异或(XOR)Rect2后得到的区域,也就在Rect1的基础上将Rect1与Rect2重合部分给挖掉之后的结果。
下面介绍下方案实现:
(图二)
- 如上图二所示,首先获取目标窗口的矩形(RECT),这个RECT就是扫描目标的区域,根据这个RECT获取对应的目标Region(通过windows系统API:“CreateRectRgn”即根据RECT获得对应的Region)。
- 以矩形框的左上角为起点,水平方向为x轴,竖直方向为y轴,按水平方向从左到右,竖直方向从上到下的方向,扫描点阵以间距为50像素为例进行扫描;首先扫描的点阵范围必在矩形框的范围内,不会超出矩形框的范围,这就可以极大的减少我们需要扫描的目标区域范围。
- 首先,在扫描过程中,不断判断当前扫描点的坐标位置是否在自己的目标Region内,如果不在,跳过即可,这样可以减少扫描区域范围,将遮盖区域范围给排除掉能一定程度提升扫描的效率。
- 其次,在扫描过程中,判断当前扫描点的坐标对应的窗口句柄(通过windows系统API:“windowFromPoint”,即传入POINT即可得到该坐标对应的句柄值),如果所得到的窗口句柄为目标窗口的句柄,表示当前扫描点位置未被其他窗口遮盖,那么继续进行下一个扫描;如果所得到的窗口句柄不是目标窗口句柄,表示当前扫描点位置已经被其他窗口遮盖,这个时候通过该句柄值获取到对应的RECT(通过windows系统的API:“GetWindowRect”获取对应窗口的RECT),然后通过Region进行异或(XOR)组合(通过windows系统的API:“CombineRgn”来进行Region的合并操作)的方式将与目标区域的重合的部分给剔除掉即可,如此再回到步骤2再进行扫描即可。
- .....
方案的改进和优化:
当然该方案还存在一些缺陷并可以做部分的改进,以下图三为例:
(图三)
如果扫描的矩阵宽度为50pix,那么扫描矩阵其实就是50*50的正方形,但如果一个条形窗口高度或者宽度小于50pix,那么点阵扫描的时候可能就因为扫描点覆盖不到该条形窗口区域而将遮盖的条形窗口给忽略掉。为此我将扫描矩阵从正方形调整优化为菱形扫描矩阵,即在水平方向上的序号为偶数的点阵向y轴方向向下调整25pix,在几乎同样的扫描矩阵点数的情况下,可以最大限度的避免遗漏掉常见的水平或竖直形状的条形矩形遮盖窗口的判断:
同时可以做非固定坐标点矩阵的实时扫描也可以最大化的减少部分较小遮盖窗的遗漏情况;同时在目标窗口的四条边界上同时做最后的矩阵扫描操作可以避免窗口边界处部分遮盖而未被扫描点覆盖到的问题。