我在WPF窗口的不透明度方面存在问题,我想要做的是更改窗口的不透明度,但保持子窗口的不透明度相同。
这是我目前的代码:
Window window = new Window();
window.WindowStyle = WindowStyle.None;
window.AllowsTransparency = true;
window.Background = Brushes.Black;
window.Opacity = 0.5;
window.ShowInTaskbar = false;
double taskBarHeight = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height;
window.Height = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - taskBarHeight;
window.Width = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width;
window.Top = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Top;
window.Left = System.Windows.Forms.Screen.PrimaryScreen.Bounds.Left;
LoginCtl ctl = new LoginCtl(this);
window.Content = ctl;
window.ShowDialog();
我知道孩子不能比他们的父母有更高的不透明度,但有可能解决这个问题吗?
答案 0 :(得分:3)
也许有助于理解窗口不透明度的工作原理。它以硬件实现,视频适配器的一项功能称为“覆盖”。它通过WS_EX_LAYERED窗口样式标志和SetLayeredWindowAttributes() api function在winapi中公开。转到该功能的MSDN Library页面,看看有什么可能。
视频适配器有一个混音器,可以组合两个视频内存缓冲区的像素。该混音器支持两种效果,alpha混合和颜色键控。分别是api函数中的bAlpha和crKey参数。 Alpha混合就是你在这里之后,它使用乘法器组合两个缓冲区的像素。 alpha乘数越低,像素对发送到监视器的最终像素值的贡献就越小。颜色键控是视频处理中的常见技巧,天气预报员在天气地图前面,当像素与颜色键匹配时,它被替换为来自另一个缓冲区的像素。颜色键控不是直接在WPF中公开,而是在Winforms中使用Form.TransparencyKey属性。 WPF使用每像素alpha,它使用包含alpha组件的32bpp像素绘制,而不像Winforms使用通过24bpp GDI调用绘制的旧本机Windows组件。
也许你现在可以告诉你为什么遇到这个问题,winapi将效果限制在一个窗口。附加要求它必须是顶级窗口,与WPF Window类相同。因此,alpha混合效果应用于所有窗口中的像素,您不能选择性地将其关闭以用于渲染控件的窗口部分。
请注意链接文章中的注释,Windows 8也支持为子窗口指定注释。这几乎肯定是由DWM,桌面窗口管理器完成的,并在启用Aero时启用。在软件而不是硬件中完成,窗口被渲染到内存,DWM在将像素发送到视频适配器之前将它们合成。该功能尚未在.NET中公开,需要时间。对WPF不是很有用,因为WPF不像Winforms那样使用子窗口。
足够的介绍,了解解决此问题需要做些什么。您需要自己进行分层。你需要两个窗口,一个在另一个上面。底部应该只是一个只有Opacity设置的普通窗口。它提供了背景。然后你需要另一个包含控件的Window,其WindowStyle设置为None,Background设置为透明,这样你就可以看到底部窗口渲染的背景像素。应将其所有者设置为底部窗口,使其始终位于顶部,当用户移动或调整底部窗口时,您需要移动并调整其大小。
答案 1 :(得分:1)
好吧,你可以让你的窗口处于正常的不透明度但是会改变背景的透明度(alpha通道)。如果这还不够,并且您想要更改chrome元素的不透明度,您可以尝试自己修改它。请参阅this link。
答案 2 :(得分:0)
我使用的解决方案可以找到here。
我所做的是创建一个只有网格和矩形的窗口:
<Grid Name="MainGrid">
<Rectangle Fill="Gray" Opacity="0.7" />
</Grid>
然后从代码后面执行以下操作:
LoginWindow win = new LoginWindow();
win.ShowInTaskbar = false;
LoginCtl ctl = new LoginCtl(this);
win.MainGrid.Children.Add(ctl);
win.ShowDialog();
通过这种方式可以看到窗口的背景,但添加到它的控件是不透明的。
希望这有助于某人!