2

我正在制作一个 .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()and Graphics.Clear(),但它要么无济于事,要么完全消除了透明度。有什么建议么?

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

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

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

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

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

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

4

2 回答 2

3

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

如果我离基地很远,你能张贴截图吗?我不知道我在想象你所描述的正确。

编辑:

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

我在 .NET 中并没有做过太多此类事情,但我之前已经很好地处理了它;就是不知道翻译好不好!

编辑2:

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

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

祝你好运!

于 2009-05-17T01:42:32.327 回答
1

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

于 2009-05-17T00:45:49.373 回答