walklang / uilib

A simply and powerful ui script framework library. via http://www.uilib.cn

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

透明窗口:WS_EX_TRANSPARENT扩展样式下,窗口鼠标消息

suhao opened this issue · comments

commented

透明窗口使用WS_EX_TRANSPARENT来实现透明,将可以利用系统的窗口混合实现自下而上的依次渲染,类似于窗口透明效果。但是针对鼠标消息,却没有WS_EX_LAYERED的穿透特性。

讨论场景:多层窗口,最顶层窗口为透明属性。在窗口层级中,可能会插入外部进程的窗口,例如使用other process实现的浏览器窗口。

一、插入窗口为同线程窗口

此种情况,我们可以简单的处理WM_NCHITTEST即可实现鼠标的穿透处理。

二、插入窗口为非同线程窗口

根据MSDN的描述,WM_NCHITTEST的测试只能在当前线程的窗口之间进行。可以参见WindowFromPoint功能。针对此种情况,我们做如下情况的分析和尝试。插入窗口我们这里简单称作InsertWindow,原窗口我们简称为Window。

  1. InsertWidow与Window之间无任何关系:非父子、非owner,可能是程序手动做了层级处理

无关窗口,却插入到原生窗口层级之间,应为手动设置了窗口层级,此种情况只能枚举系统窗口来查找和判断窗口是否重叠。

  1. InsertWindow与Window:父子窗口

父子关系窗口,我们可以使用EnumchildWindow来枚举窗口,判断窗口显示、位置重叠;然后可以尝试如下几种方式,第一种Window的ncHitTest返回HTNOWHERE看系统是否可以查找到响应窗口,第二种消息转发,第三种模拟鼠标操作。

  1. InsertWindow与Window:owner关系

owner关系类似于父子关系处理。

不同线程不知道是否可以hook窗口过程函数? 如果可以就可以监听窗口位置和显示隐藏状态,不然就需要时时刻刻来进行窗口状态的判断。

三、从应用的角度分析如上问题

同线程的对逻辑处理无任何影响,不同线程的插入窗口若无关系窗口可以不考虑,我们更多的是处理自身的相关窗口逻辑。

  1. owner关系窗口:owner插入的窗口应该是想要实现透明,利用popup窗口实现。在win10上可以使用子窗口替代实现,在win10以下系统,我们自身的原有窗口也只能使用Layered窗口,故而不存在此问题。

  2. 父子关系窗口:子窗口不管是否有透明属性,不管系统如何处理的融合渲染以及对展示是否有影响。我们只是想要处理鼠标穿透,故而其他都不做扩展讨论。在nchittest时,检测insertWindow为非client区域则应由原生窗口来响应鼠标消息,客户区则需要进行HTNOWHERE或者鼠标消息转发处理。不同线程的窗口,在NCHITTEST时,是否可以设置SetFoucs、setCapture、SetActivate等给InsertWindow? 是否会有效果?

四、测试实验

  1. HTNOWHERE:经过实验,对NCHitTest返回HTNOWHERE时,系统并不会继续去测试窗口层级下方的窗口。故而此种方法直接被废。

  2. 是否可以激活InsertWindow?

  3. 是否可以进行消息转发?

  4. 是否可以进行鼠标模拟?

commented

再次解读MSDN关于鼠标消息的处理,NCHITTEST反复强调要在同一个线程,想到AttachThreadInput。

根据MSDN的描述,这个API可以将鼠标消息在两个线程之间共享。我们是否可以尝试看看是否有效呢?