0

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

我知道孩子的不透明度不能比他们的父母高,但是有没有可能的解决方法?

4

3 回答 3

4

也许它有助于理解窗口不透明度是如何工作的。它在硬件中实现,视频适配器的一项功能称为“覆盖”。它通过 WS_EX_LAYERED 窗口样式标志和SetLayeredWindowAttributes() api 函数在 winapi 中公开。转到该功能的 MSDN 库页面以查看可能的功能。

视频适配器有一个混合器,可以组合两个视频内存缓冲区的像素。该混合器支持两种效果,阿尔法混合和颜色键控。分别是 api 函数中的 bAlpha 和 crKey 参数。Alpha 混合是您在这里所追求的,它使用乘数将两个缓冲区的像素组合在一起。alpha 乘数越低,像素对发送到监视器的最终像素值的贡献就越小。颜色键控是视频处理中的常见技巧,天气预报员在天气图前,当一个像素与颜色键匹配时,它将被另一个缓冲区中的像素替换。颜色键控不直接在 WPF 中公开,但在 Winforms 中具有 Form.TransparencyKey 属性。WPF 使用每像素 alpha,它使用包含 alpha 分量的 32bpp 像素进行绘制,

也许您现在可以说出为什么会遇到这个问题,winapi 将效果限制在一个窗口中。附加要求它必须是顶级窗口,与 WPF Window 类相同。因此,alpha 混合效果适用于窗口中的所有像素,您不能有选择地将其关闭用于渲染控件的窗口部分。

请注意链接文章中的评论,Windows 8 也支持为子窗口指定它。这几乎肯定是由桌面窗口管理器 DWM 完成的,并在启用 Aero 时启用。在软件而不是硬件中完成,窗口被渲染到内存,DWM 在将像素发送到视频适配器之前对它们进行合成。该功能尚未在 .NET 中公开,需要时间。反正对 WPF 不是很有用,因为 WPF 不像 Winforms 那样使用子窗口。

足够的介绍来理解你需要做什么来解决这个问题。你需要做自己的分层。你需要两扇窗户,一扇夹在另一扇上面。底部应该只是一个普通的窗口,只有不透明度集。它提供了背景。然后,您需要另一个包含控件的 Window,将其 WindowStyle 设置为 None 并将 Background 设置为 transparent,以便您可以看到底部窗口呈现的背景像素。它的所有者应该设置为底部窗口,因此它始终位于顶部,并且当用户移动底部窗口或调整其大小时,您需要移动它并调整其大小。

于 2012-11-22T12:37:14.650 回答
1

好吧,你可以让你的窗口处于正常的不透明度,但改变背景的透明度(阿尔法通道)。如果这还不够,并且您还想更改 chrome 元素的不透明度,您可以尝试自己修改它。请参阅此链接

于 2012-11-22T11:46:51.663 回答
0

我使用的解决方案可以在这里找到。

我所做的是创建一个只有一个网格和一个矩形的窗口:

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

这样可以看到窗口的背景,但添加到其中的控件是不透明的。

希望这对某人有帮助!

于 2012-11-26T07:14:57.663 回答