我正在制作一个 .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;
我将尝试为透明部分创建一个单独的窗口,如 overslacked 提到的,但仍然欢迎任何其他想法。
最佳答案
实际上,我想我会称之为预期行为。我要做的是将背景渲染到内存中的位图,然后在绘制事件中将其复制到表单(基本双缓冲)。
如果我离基地很远,你可以发布屏幕截图吗?我不知道我的想象是否正确。
编辑:
我想知道你对 OnPaintBackground 的使用...在 .NET 之前,如果你正在进行双缓冲,你会捕获并忽略 WM_ERASKBKGND 消息(以防止闪烁),将图像渲染到屏幕外缓冲区,并在 WM_PAINT 上从缓冲区复制到屏幕。因此,请尝试从 OnPaintBackground 更改为 OnPaint。
我在 .NET 中没有做过太多这样的事情,但我以前已经很好地处理过它了;只是不知道翻译得好不好!
编辑2:
马克,我越想你想做的事情,就越出现问题。我打算建议创建一个专门用于捕获屏幕并将其渲染变暗的后台线程;但是,为了删除您自己的表单,您必须将可见性设置为 false,这会产生其他问题......
如果你不愿意放弃,我建议创建两个窗口并将它们“绑定(bind)”在一起。为背景窗口创建一个半不透明窗口(通过设置不透明度),并为前景创建第二个“正常”窗口。在前景窗口上使用 SetWindowRgn 来切除背景并将它们放置在彼此的顶部。
祝你好运!
关于c# - C# .NET 3.5 WinForms 部分透明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/873470/