【问题标题】:Partial transparency with C# .NET 3.5 WinForms?C# .NET 3.5 WinForms 的部分透明度?
【发布时间】:2010-10-26 18:51:45
【问题描述】:

我正在制作一个 .NET 3.5 应用程序,其表单绘制了部​​分透明的黑色背景。我正在重写 OnPaintBackground 来完成此操作:

protected override void OnPaintBackground( PaintEventArgs e )
{
    using ( Brush brush = new SolidBrush( Color.FromArgb( 155, Color.Black ) ) )
    {
        e.Graphics.FillRectangle( brush, e.ClipRectangle );
    } 
}

它可以工作,但有时表单会在不清除屏幕的情况下自行绘制,从而使透明度比应有的更暗。我尝试过使用Graphics.Flush()Graphics.Clear(),但它要么无济于事,要么完全消除了透明度。有什么建议吗?

编辑: 下面是它的样子,在左侧启动应用程序之后,在右侧表单重绘自身几次(以响应从一个控件到另一个控件的切换)之后:

Transparency Issue http://www.quicksnapper.com/files/5085/17725729384A10347269148_m.png

编辑 2: 今天早上我尝试了一些事情,并注意到当透明部分后面的桌面发生变化时,它实际上并没有被重绘。例如,如果我打开任务管理器并将其放在窗口后面,您不会看到它自行刷新。这与我在透明度级别上看到的情况是有道理的。是否有让 Windows 重绘窗口后面区域的功能?

编辑 3: 我尝试更改表单上的一些属性,但它们都导致表单绘制不透明的黑色:

this.AllowTransparency = true;
this.DoubleBuffered = true;
this.Opacity = .99;

我将尝试为透明部分创建一个单独的窗口,正如提到的过度松弛,但仍然欢迎任何其他想法。

【问题讨论】:

  • 这是您无法设置 Opacity 属性的情况吗?
  • 是的,我不希望表单的控件是透明的,只是窗口背景的一部分。
  • 这是在启用 Aero 的 Vista 上吗?知道这一点会很有用,这样我就可以自己尝试解决这个问题。
  • 目前只是Windows XP,我还没有开始在Vista上测试。
  • Marc,任务管理器“不刷新自身”的问题实际上是您的应用程序没有重新绘制。尽管您是半透明地绘制的,但实际的窗口仍然是 100% 不透明的。这就是 Demi 建议使用 Opacity 属性的原因。我将在下面更新我的答案,为您提供另一个想法。

标签: c# .net winforms drawing transparency


【解决方案1】:

实际上,我想我会称之为预期行为。我要做的是将我的背景渲染到内存中的位图,然后在绘制事件中将其复制到表单(基本双缓冲)。

如果我离基地很远,你能发布截图吗?我不知道我在想象你描述的是否正确。

编辑:

我想知道您使用 OnPaintBackground... pre-.NET,如果您正在执行双缓冲,您会捕获并忽略 WM_ERASKBKGND 消息(以防止闪烁),将您的图像渲染到屏幕外缓冲区,并从缓冲区复制到 WM_PAINT 上的屏幕。因此,请尝试从 OnPaintBackground 更改为 OnPaint。

我在 .NET 中没有做过太多这类事情,但我之前对它有很好的处理;就是不知道翻译好不好!

编辑 2:

马克,我越想你想做的事,问题就越多。我打算建议创建一个专门用于捕获屏幕并使其变暗的后台线程;但是,为了删除您自己的表单,您必须将可见性设置为 false,这会产生其他问题....

如果您不愿意放弃,我建议创建两个窗口并将它们“绑定”在一起。为您的背景窗口创建一个半透明窗口(通过设置不透明度),并为前景创建第二个“正常”窗口。在前景窗口上使用 SetWindowRgn 将背景切掉并将它们放在彼此的顶部。

祝你好运!

【讨论】:

  • 我试了一下(创建了一个新的位图,从图像创建了一个图形,以与上面相同的方式填充它,并使用绘制事件的图形将其绘制到屏幕上)并且它具有同样的问题。不过,这不是一个坏主意,还有其他方法可以将图像绘制到屏幕上吗?
  • 我已经用其他方法更新了我的答案;如果您有任何代码可以发送,它与 gmail 的用户名相同,我会看看是否可以提供任何帮助。
  • 谢谢,我会试试双窗口选项,看看我能不能做到这一点。
  • 我最终创建了第二个透明背景窗口,现在我开始做生意了。感谢大家的帮助!
【解决方案2】:

Graphics.CompositingMode 是否设置为 CompositingMode.SourceCopy?这应该会导致两次绘制背景等同于绘制一次,因为它将替换现有的 alpha/color 数据而不是对其进行合成。

【讨论】:

  • 好建议,但是当我将其设置为 SourceCopy 时,它会破坏任何透明度,只会绘制不透明的黑色背景。
  • 我不确定是否有任何方法可以通过纯 WinForms 获得您想要的行为。您可以使用 P/Invoke 直接访问分层窗口 API 并为您的窗口设置每像素 alpha 透明度,但我不确定这是否值得。您是否考虑过使用 TransparencyKey 让表单的非 UI 部分显示出来,然后在其后面放置一个部分不透明的窗口以创建所需的效果?
猜你喜欢
  • 1970-01-01
  • 2014-09-17
  • 2014-04-22
  • 2014-06-16
  • 2015-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-26
相关资源
最近更新 更多