改变窗口的不透明度让孩子们一样

时间:2012-11-22 11:34:55

标签: c# wpf

我在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();

我知道孩子不能比他们的父母有更高的不透明度,但有可能解决这个问题吗?

3 个答案:

答案 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();

通过这种方式可以看到窗口的背景,但添加到它的控件是不透明的。

希望这有助于某人!