非客户端绘制窗口上的Aero玻璃效果

38

现在我正在自定义应用程序的标题栏。我的目标是在标题栏上添加一个额外的按钮。在我的之前的问题中,人们建议我可以自定义非客户区域的方式。这个方法完美运作,除了一个小问题 - 发光!我可以在非客户区域绘制发光效果,但我无法将其扩散到窗口之外。我也找不到任何关于此主题的资源。

我查看了这个示例,并创建了自己的测试应用程序来调查非客户端绘图功能。我的应用程序窗口的屏幕截图如下:

my app's window

所以您可以看到当我的窗口被边框框架裁剪时,系统按钮会发光超出窗口。

例如,Skype的窗口在标题栏中有四个自定义按钮,它们可以在窗口框架外部“发光”:

Skype's window

有人能为我提供建议,找到绘制按钮在窗口外部发光的方法吗?
提前感谢!

[编辑]
谢谢大家的回答!


2
尽管 Skype 界面令人作呕,但其窗口的非客户区域给我留下了异常积极的印象。 - BoltClock
例如,Skype的窗口在标题栏中有四个自定义按钮。这是否意味着Skype正在绘制整个UI(包括阴影),而不仅仅是按钮? - Random832
@Random832:嗯,我没有从那个角度考虑过这个问题。我有模糊的猜测,这很可能是真的。谢谢!你知道如何检查这个吗? - Anton Semenov
1
有些事情比看起来更难。例如,很久以前我不得不浏览大量文章和代码,才能在玻璃上绘制带有发光效果的字符串(就像标题栏中的那样)。我相信有一种方法可以做到这一点,但我认为这并不容易,因为它必须与WDM兼容 - 或许联系Skype团队会更好。 - Alireza Noori
2
顺便提一下,Chromium现在可以做到这一点(它添加了一个“登录”按钮)。 - paulm
显示剩余6条评论
3个回答

14

Skype作弊,窗口顶部有一个小片段;可以在上面绘图。

您可以使用Process Explorer和SpyXX查看它:

enter image description here

另请参阅

MSDN:使用DWM自定义窗口框架


今天我注意到Chrome有全尺寸的实际主题按钮。而Skype则有一些自定义按钮,与主题并不完全相同。而Spyxx在Chrome(或者Office 2007,那也绘制在NC区域)上方没有显示边框。所以肯定有解决方案。我试着浏览了Chromium源代码,但是找不到WM_NCPAINT处理程序。 - Ian Boyd
@Ian:那些按钮是系统绘制的。这样的界面是通过自定义窗口框架创建的。您可以在此处阅读更多信息http://msdn.microsoft.com/en-us/library/bb688195.aspx。 - Anton Semenov
@Anton Semenov 这相当...没有记录。DWM只是“恰好”绘制系统按钮 - 即使我从未要求过?难怪这毫无意义 - 它毫无意义! - Ian Boyd
@Anton Semenov:一个具有特定样式的窗口会导致DWM在我的客户区域绘制最小化、最大化或关闭框,而不是非客户区域? - Ian Boyd
@Ian:这是一个令人困惑的时刻。这些按钮总是绘制在非客户区域或在您扩展客户区域之前的那个位置。您可以“删除标准框架”(如“使用DWM自定义窗口框架”文章中所述),但按钮仍将被绘制,此时您可以在系统按钮周围绘制任何您喜欢的内容,但系统按钮仍将被绘制。因此,如果您有窗口框架,可以强制WDM绘制系统按钮,在这种情况下,您是否控制非客户端绘画都无关紧要。 - Anton Semenov
显示剩余2条评论

5
我认为不可能超出您的NC区域进行绘图,并且我有点怀疑他们会绘制整个UI以完全匹配DWM Aero效果。 考虑到这个,我想知道他们是否使用了CustomBorderForm的帮助或恢复按钮的一些技巧,然后可以“免费”获得DWM模糊高亮效果。
下面是我能找到的与此最相关的文章: http://geekswithblogs.net/kobush/articles/CustomBorderForms3.aspx 跟进 - 我认为这个自定义Chrome线程有更多指向同样技术的指针(虽然不同的目标): Custom titlebars/chrome in a WinForms app

谢谢你的回答!我会按照你的建议尝试操作系统按钮。 - Anton Semenov
没问题 - 在这里还有更多的源代码可以挖掘: http://customerborderform.codeplex.com/ - holtavolt

3
据我所知,这是不可能的,因为窗口边框外的区域根本不属于你。
Skype的截图来自一个自定义绘制的框架,很可能超出了可见边界,而不是来自Aero Glass框架。如果仔细观察,你可以看出区别。

实际上,你是可以的。这是一种高级技术,由于在Windows 8、Windows 9、Windows 10等操作系统中该区域的绘制方式不同,这将引发一系列问题,并且会带来许多未来的麻烦。虽然你可以在非客户区绘制,但并不总是能够准确确定其中的内容以及你自定义绘制的整体效果,因为随着时间的推移和Windows操作系统的变化,这些都会发生改变。 - Warren P
这是完全可能的,但非常困难。 - David Heffernan
2
我的回答在这里:https://dev59.com/WGsz5IYBdhLWcg3wNU8R,链接到一些提供示例Delphi代码的帖子。 - David Heffernan
@DavidHeffernan:感谢您提供的链接。我正在查看它们,但从我所了解的内容来看,它们只告诉你如何在非客户区域内进行绘制(很容易,只需调用GetWindowDC),而不是如何在外部进行绘制(这就是OP询问的内容,用于绘制阴影/光晕)。我是否误读了这些文章? - user541686
1
“窗口边框外的区域并不属于你”这句话并不准确。窗口外的区域属于支持窗口的同一DirectX表面。虽然它可能不易访问,也不属于你所有,但它仍然存在,并且是窗口不可分割的一部分。 - IInspectable
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接