使用C#.NET 3.5 WinForms进行部分透明化?

我正在制作一个.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() ,但它无法帮助或完全删除透明度。 有什么建议?

编辑:在左侧启动应用程序后,以及在右侧重新绘制表单几次(以响应从一个控件到另一个控件的选项卡)后,它的外观如下:

透明度问题http://www.quicksnapper.com/files/5085/17725729384A10347269148_m.png

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

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

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

我将尝试为透明部分创建一个单独的窗口,如上所述,但仍然欢迎任何其他想法。

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

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

编辑:

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

我在.NET中没有做过太多这样的事情,但我以前处理得很好; 我只是不知道它是否会好好翻译!

编辑2:

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

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

祝好运!

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