使用分层窗口创建平滑的窗口边框

时间:2009-04-13 21:06:00

标签: windows winapi alpha layered

我们正在开发一款带有各种圆形边缘的皮肤应用程序。我使用窗口区域来定义非矩形形状,但是几乎所有人都反对这种锯齿状别名,因为像素只能是完全不透明或完全透明。

我已经使用分层窗口提出了一个解决方案,但我们想确保在各种系统上运行(并希望运行良好),我想看看是否有人有更好的想法,或者优化我正在做的事情的方法。我知道分层窗口需要win2000或更高版本,这很好,因为这已经是其他原因的要求。从一些基本测试来看,它在Vista上看起来还不错,但目前还不能保证。

这就是我所做的:我有一个窗口,称之为A,带有控件和文本以及包含该窗口的任何内容。我有窗口B作为窗口A的子窗口,除了它具有WS_POPUP样式而不是WS_CHILD,因此它可以将自己定位在A的区域之外并绘制在A的控件之上。窗口B也具有WS_EX_LAYERED样式,在初始化时,我使用ULW_ALPHA标志调用UpdateLayeredWindow,使用带有alpha通道的32位位图调用源DC,以使其以每像素alpha绘制。

窗口B的源DC中使用的位图几乎就是窗口边框周围的像素,我希望从窗口的背景平滑地混合到完全透明。我会跳过整个两个窗口的方法,只使用单个分层窗口,除了当你使用UpdateLayeredWindow时,它是从保存在内存中的缓冲区中提取的,代替典型的WM_PAINT消息和所有这些,并试图获取交互式儿童控件(和子窗口)能够很好地协同工作,这听起来非常麻烦(甚至可能不适用于所有事情)。

所以,它基本上是窗口A,包含所有子控件等等,窗口B直接浮在它上面,画出一个漂亮的光滑边框。我通过移动窗口B来响应WM_MOVE消息等,并且我禁用了窗口B,因此它永远不会获得焦点或输入(点击已经通过,因为它的部分是不透明的,例如大多数它的内部部分已被排除在采摘之外。

对于踢球,这就是这些棋子的样子,以表明我的意思更好一点。

所以,它有效,但我无法确定它是否真的是最好的方法。我有两个问题:

  • 这听起来可以接受,还是有什么明显可怕的呢?
  • 因为它目前的工作原理,它似乎是使用窗口大小的屏幕外缓冲区(可以达到1024x768),即使它的极少数像素有任何非零不透明度数据 - 它会是是否值得花费额外的复杂性,将其切割成单独的边框并将它们合成在一起?

3 个答案:

答案 0 :(得分:3)

我发现了一件事:拥有单独的框架部件可以比使用一个巨大的框架窗口快得多,中间有大量的空像素。我没有任何实际的数字,但只是通过快速测试两者,当几个窗口与全帧窗口相互重叠时,有明显的延迟,但当他们的帧被切割成较小的组件时,它是更加快捷的。使用具有自己的设备上下文的多个分层窗口的任何开销都没有多大贡献,并且具有大量像素(空白或不是!)仍然会带来更多负载。

答案 1 :(得分:2)

我的产品使用分层窗口绘制我附加到每个窗口的小标签。我使用分层窗口来获得平滑的圆角而没有锯齿。到目前为止我遇到的唯一令人讨厌的问题是,一些OpenGL窗口在没有DWM的Windows XP和Vista上的分层窗口上涂鸦。它是一个低级别的问题,微软并没有非常有用。您可以通过打开Goog​​le地球并在主渲染窗口上拖动应用程序来重现它,您的分层窗口将会消失。

答案 2 :(得分:1)

  1. 不要忘记在RDP和VM(Hyper-V& VMWare)下进行测试
  2. 尝试使用几张gfx卡以及上网本和笔记本电脑(如果适用)。