用C#.NET 3.5的WinForms部分透明度?透明度、部分、NET、WinForms

2023-09-03 01:15:58 作者:心脏有多脏,

我在做一个.NET 3.5的应用程序与绘制一个部分透明的黑色背景的一种形式。我重写OnPaintBackground做到这一点:

I'm making a .NET 3.5 app with a form that draws a partially transparent black background. I'm overriding OnPaintBackground to accomplish this:

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()玩,但它要么不帮助或完全消除透明度。有什么建议?

It works, but occasionally the form draws over itself without clearing the screen, making the transparency darker than it should be. I've tried playing with Graphics.Flush() and Graphics.Clear(), but it either doesn't help or completely removes transparency. Any suggestions?

编辑: 这里是什么样子,从左边的应用程序后,经过形式重绘自​​己几次(响应从一个控制tab键切换到另一个)右侧:

Here's what it looks like, after starting the app on the left, and after the form redraws itself a few times (in response to tabbing from one control to another) on the right:

编辑2: 我尝试了一些东西今天上午,发现当透明部分后面的桌面上改变,它实际上没有被重新绘制。举例来说,如果我打开任务管理器,并把它放在窗口后面,你看不到它刷新自己。这是有道理的什么我已经看到的透明度水平。是否有一个功能,让Windows重画你的窗口后面的区域?

Edit 2: I was trying a few things out this morning and noticed that when the desktop behind the transparent portions change, it's not actually being redrawn. For example, if I open Task Manager and put it behind the window, you don't see it refreshing itself. This makes sense with what I've been seeing with the transparency levels. Is there a function to make Windows redraw the area behind your window?

修改3: 我试着在表单上改变一些属性,但他们都结果的形式绘制非透明黑色:

Edit 3: I've tried changing a few properties on the form, but they all result in the form drawing non-transparent black:

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

我会尝试创建一个单独的窗口透明部分为overslacked提到的,但是任何其他的想法,仍然欢迎。

I'm going to try creating a separate window for the transparent portion as overslacked mentioned, but any other ideas are still welcome.

推荐答案

我想我会称这种预期的行为,其实。我会做的是使我的背景到一个内存位图,在绘制事件,复制到窗体(基本的双缓冲)。

I think I would call this expected behavior, actually. What I would do is render my background to an in-memory bitmap and, in the paint event, copy that to the form (basic double-buffering).

如果我是大错特错,你能张贴截图?我不知道,我想象你所描述正确的是什么。

If I'm way off base, could you post a screenshot? I don't know that I'm imagining what you're describing correctly.

编辑:

我想了解一下您使用OnPaintBackground ... pre-.NET的,如果你做双缓冲你会赶上并忽略WM_ERASKBKGND消息(以prevent闪烁),使您的图像屏幕外缓冲区,从缓冲区复制到WM_PAINT屏幕。因此,尝试从OnPaintBackground到的OnPaint改变。

I'm wondering about your use of OnPaintBackground... pre-.NET, if you were doing double-buffering you'd catch and ignore the WM_ERASKBKGND message (to prevent flicker), render your image to an offscreen buffer, and copy from the buffer to the screen on WM_PAINT. So, try changing from the OnPaintBackground to OnPaint.

我没有做太多这种在.NET中的事情,但我以前有一个pretty的手感好就可以了;我只是不知道这是否会转化得好不好!

I haven't done too much of this kind of thing in .NET, but I had a pretty good handle on it before; I just don't know if it'll translate well or not!

编辑2:

马克,我越觉得你想要做什么,更多的问题出现。我要建议建立专门捕捉屏幕,使得它黑暗的后台线程;然而,为了消除自己的表单,你不得不能见度设置为false,这会带来其他问题......

Marc, the more I think about what you're trying to do, the more problems appear. I was going to suggest creating a background thread dedicated to capturing the screen and rendering it darkened; however, in order to remove your own form you'd have to set the visibility to false which would create other problems....

如果你不愿意放弃,我会建议创建两个窗口和捆绑在一起。创建一个半透明的窗口(通过设置不透明度)对你的背景窗口,创建第二个正常窗口前台。使用在前景窗口SetWindowRgn到切掉背景和它们在彼此的顶部定位

If you're unwilling to give up, I would suggest creating two windows and "binding" them together. Create a semi-opaque window (by setting opacity) for your background window, and create a second "normal" window for the foreground. Use SetWindowRgn on the foreground window to cut away the background and position them on top of each other.

祝你好运!