DWM 组合切换导致客户区域丢失 Alpha

发布于 2024-08-06 00:03:09 字数 1077 浏览 6 评论 0原文

我这里有一个简单的 Windows 应用程序:

http://www.bengoodger.com/ software/chrome/dwm/app.cc

我的应用程序在 DWM 合成处于活动状态时提供自定义的玻璃框架,在不活动或不可用时提供完全自定义的框架。

“定制玻璃框架”由放大的标题栏区域组成,我的 WM_NCCALCSIZE 实现将其报告为客户区域的一部分,因为我想将透明控件渲染到其中。为了使窗口的“高标题栏区域”部分是透明的,我用透明黑色(上面的简单示例中的 BLACK_BRUSH)填充它,这导致它被 DWM 绘制为玻璃。

当系统 DWM 切换时,例如通过使用“外观设置”控制面板切换到 Vista Basic 或 Windows Standard,或者当启动需要系统禁用 DWM 的应用程序时,我的应用程序通过处理 WM_NCPAINT 等切换到完全自定义渲染模式当我切换回来时,我预计会发生相反的情况,除了我的“高标题栏区域”现在是纯黑色。

我发现我可以通过获取窗口的位置、隐藏窗口然后在 WM_DWMCOMPOSITIONCHANGED 处理中再次设置窗口的位置来解决此问题,但这会导致其他可怕的错误(至少是窗口 z 顺序修改)。

我的问题是 - 我在这里做错了什么?看起来窗口不知何故被置于虚假状态,隐藏/显示它可以纠正它。我怎样才能防止这种情况发生?任何指导将不胜感激。

注意:我已经缩小了范围。当 DWM 玻璃生效时,在客户区域上渲染的任何涂成黑色的客户区域部分都会呈现透明。我们注意到,当从非 Glass 返回 Glass 时,客户区域会呈现纯黑色而不是透明。但是,当窗口最大化然后恢复时,窗口将恢复透明。当我随后将窗口尺寸拖动得较小时,顶部窗口保持透明。当我将其拖动得更大时,窗口的顶部再次变黑。这就好像 DWM 正在缓存窗口后面的像素,并且将窗口调整得较大会导致它无法在那里绘制任何内容,因为它的缓存不够大。我似乎找不到任何 DWM 函数来重置此状态。看起来“最大化/最小化”然后“恢复”或“SetWindowPlacement”虽然能够解决这个问题,但也会产生其他不良副作用。

I have a simple Windows application here:

http://www.bengoodger.com/software/chrome/dwm/app.cc

My app provides a customized glass frame for when DWM compositing is active, and a fully custom frame when it is inactive or not available.

The "customized glass frame" consists of a enlarged title bar area, which is reported by my implementation of WM_NCCALCSIZE to be part of the client area since I would like to render transparent controls into it. So that this "tall title bar area" portion of my window is transparent, I fill it with transparent black (BLACK_BRUSH in the simple example above) which causes it to be drawn as glass by the DWM.

When the system DWM is toggled, e.g. by using the Appearance Settings control panel to switch to Vista Basic or Windows Standard, or when an app that requires the system to disable DWM is launched, my app switches to fully custom rendering mode by handling WM_NCPAINT etc. When I switch back, I would expect the reverse, which mostly happens, except my "tall title bar area" is now solid black.

I've found I can work around this issue by getting the window's placement, hiding the window then setting the window's placement again in my WM_DWMCOMPOSITIONCHANGED handling, but this causes other horrible bugs (least of which is window z-order munging).

My question is - what am I doing wrong here? It seems like the window is being put into a bogus state somehow, and hiding/showing it corrects it. How can I prevent this from happening? Any guidance would be greatly appreciated.

Note: I have narrowed this down somewhat. When DWM glass is in effect, any part of the client area that is painted black that is rendered over the client area is rendered transparent. We noticed that when returning to Glass from non-Glass, the client area is rendered solid black instead of transparent. However when the window is maximized and then restored, the window returns to being transparent. When I subsequently drag size the window smaller, the top portion window remains transparent. When I drag it larger, the top portion of the window turns black again. It's as if the DWM is caching the pixels behind the window and sizing the window larger causes it not to be able to paint anything there because its cache isn't large enough. I can't seem to find any DWM function to reset this state. It seems that Maximize/Minimize then Restore or SetWindowPlacement are capable of tickling it though but have other undesirable side effects.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

黑凤梨 2024-08-13 00:03:09

http://www.codeproject.com/KB/dialog/rtaGlassEffectLib.aspx

正如您可能已经注意到的,
GlassEnabled 属性是一个很棒的属性
用于测试该功能是否启用
通过您的系统,然后开始使用
我们的库并调用 ShowEffect()
函数来显示玻璃效果,现在
假设用户已禁用/启用
您的应用程序中的 Aero 主题
正在运行!这可能会导致
你的外表有问题
应用程序。

为了解决这个问题,发生了两个事件
添加到库中以进行跟踪
系统发生的变化
当您的应用程序运行时,
这两个事件是
GlassEffectEnabled 事件和
玻璃效果已禁用。

现在对于那些想知道如何做的人来说
东西有效..我可以说这些
事件是通过监控来实施的
来自系统的消息
我们的应用程序的窗口看起来
对于 WM_SYSCOLORCHANGE 消息
表示系统颜色有
被改变了。因此,通过快速执行
之间的状态比较
GlassEnabled 属性之前和之后
这条消息,我们可以决定是否
该功能是否已启用。

http://www.codeproject.com/KB/dialog/rtaGlassEffectLib.aspx

As you may have noticed, the
GlassEnabled property is a great one
for testing if this feature is enabled
by your system and then start using
our library and call ShowEffect()
function to show the glass effect, Now
suppose the user has disabled/enabled
the Aero Theme while your application
was running !! This may cause a
problem in the appearance of your
application.

To solve this problem, two events were
added to the library to keep track of
the changes happening to the system
while your application is running,
these two events are
GlassEffectEnabled event and
GlassEffectDisabled.

Now for people who like to know how
stuff works .. I can tell that these
events were implemented by monitoring
the messages coming from the system to
the windows to our application looking
for the WM_SYSCOLORCHANGE message that
indicates that the system colors have
been changed. So by doing a quick
compare between the state of the
GlassEnabled property before and after
this message, we can decide whether
this feature has been enabled or not.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文