layered window

layered window, 中文似乎翻成分层窗口, 是windows 为了提高不规则窗口而提供的窗口类型. 某些calender 类的软件中, 那些顶层的半透明的窗口大多应该都是layered window. 常用的API 就2个: UpdateLayeredWindow(), SetLayeredWindowAttributes(). 但是使用layered window 有2个限制:

1. layered window 的style 不能设为WS_CHILD. 会抛错= =b


2. layered window 会ignore WM_PAINT 消息. 这句是msdn 上的原话. 经过实践, 这句话的意思是说, layered window 根本就收不到WM_PAINT 消息, 估计是windows 根本就没有dispatch 这个消息.
    第二个限制带来的麻烦就是, 如果一个窗口上有button啊之类的子控件, 那么设置成layered window 之后, 这些控件都画不出来了=v=.

 

有3种方法可以解决问题:

1. 既然收不到WM_PAINT, 那么就自定义一个message 类型, 然后加一个Timer 给自己发这个message 来重画窗口. 这个我没试过也.

2. 用2个window, a, b. a是一般window, b是layered window. a 包含有控件, 把a 的alpha 值设成透明, 于是透过a 就可以看到b 了. 现在我们要做的是把a 的screenshot 贴到b 上去, 由于a 是可以收到WM_PAINT 消息的, 所以重画应该是正常的. 这个贴的过程要用到window 的WM_PRINT 消息(注意拼写). 具体可以参考这里: A VISTA style dialog for windows 2000/xp/2003.但是这样做是有问题的: 首先不是所有的控件都实现了对于WM_PRINT 的处理. 其次, 输入框里的光标是画不出来的.
3. 还是用2个window. 一般一定要用到layered window 的地方, 窗口的边框都会是一个渐变, 比如像vista 下面的shadow. 所以我们可以把空间话在一个普通的window 上, 而边框用layered window, 然后保证 layered window 比普通window 大就可以了. 这个方法我觉得是最好的了.


4. 最无语的时候, 就是要求一个window 中间是透明的, 但是子控件不透明. 由于控件的透明度是依赖window 透明度的, 所以不是简单的设一个透明度就可以的了, 必须要用到layered window. 那么我们怎么让中间透明, 但是又添加控件呢? 这是一个很很很很很无语的方法. 就是子控件全部都贴图, 然后根据鼠标位置, 消息, 来模拟button 之类的功能. 这种情况就是本次project 遇到的, 唉唉.

### 回答1: 这条代码设置了一个窗口的扩展样式,其中包含了 WS_EX_TOPMOST、WS_EX_LAYERED、WS_EX_TRANSPARENT 和 WS_EX_TOOLWINDOW 四种样式。其中,WS_EX_TOPMOST 表示这个窗口总在最上面,WS_EX_LAYERED 表示这个窗口使用颜色加权混合方式绘制,WS_EX_TRANSPARENT 表示这个窗口是透明的,WS_EX_TOOLWINDOW 表示这个窗口是一个工具窗口。这条代码将扩展样式设置为这些样式的组合,从而使得鼠标可以穿过窗体,直接点击桌面。但是,这条代码并没有提供取消鼠标穿透的方法。如果想要取消鼠标穿透,你可以将窗口的扩展样式设置为不包含 WS_EX_TRANSPARENT 的样式,这样就可以解除鼠标穿透效果了。 ### 回答2: 使用SetWindowLong函数来设置窗口的扩展样式,包括WS_EX_TOPMOST、WS_EX_LAYERED、WS_EX_TRANSPARENT和WS_EX_TOOLWINDOW。其中WS_EX_TOPMOST将窗口设置为最顶层,WS_EX_LAYERED使窗口支持透明效果,WS_EX_TRANSPARENT使窗口透明,并且允许鼠标穿透,WS_EX_TOOLWINDOW将窗口标识为工具窗口。 通过使用以上代码,可以使鼠标可以穿过窗体,直接点击桌面。但是在没有其他的代码进行修改的情况下,无法取消鼠标穿透。如果要取消鼠标穿透,需要进行进一步的操作。 可以使用以下代码取消鼠标穿透功能: SetWindowLong(_hwnd, GWL_EXSTYLE, GetWindowLong(_hwnd, GWL_EXSTYLE) & ~WS_EX_TRANSPARENT); 通过使用GetWindowLong函数获取当前窗口的扩展样式,并且取消WS_EX_TRANSPARENT标志位,最后通过SetWindowLong函数重新设置窗口的扩展样式。 注意:以上操作仅针对当前窗口进行修改,如果要取消其他窗口的鼠标穿透功能,需要在相应的窗口句柄上进行相同的操作。 ### 回答3: 使用SetWindowLong函数设置窗体的扩展样式,包括WS_EX_TOPMOST(窗体置顶)、WS_EX_LAYERED(窗体透明)、WS_EX_TRANSPARENT(鼠标穿透)和WS_EX_TOOLWINDOW(工具窗口)。通过将这些扩展样式使用按位或运算符合并在一起,通过_hwnd参数指定窗体的句柄,可以使鼠标可以穿过窗体直接点击桌面。 然而,根据提供的代码,没有提供取消鼠标穿透的方法。调用SetWindowLong函数并设置新的窗体扩展样式后,将无法通过类似的方式来取消鼠标穿透。如果要取消鼠标穿透,需要重新调用SetWindowLong函数,并在GWL_EXSTYLE参数中使用原始窗体的扩展样式,而不包括WS_EX_TRANSPARENT。这将覆盖之前设置的样式,从而实现取消鼠标穿透的效果。 具体的代码示例如下: ```c++ // 设置窗体的扩展样式,包括鼠标穿透 SetWindowLong(_hwnd, GWL_EXSTYLE, WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW); // 要取消鼠标穿透,重新设置窗体的扩展样式,将原始样式设置回去(不包括WS_EX_TRANSPARENT) SetWindowLong(_hwnd, GWL_EXSTYLE, originalExStyle); ``` 需注意的是,originalExStyle代表窗体在调用SetWindowLong函数前的扩展样式,需要在调用该函数之前保留该值,以便在取消鼠标穿透时恢复窗体的原始样式。 希望以上解答能对您有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值