+1  A: 

Is Graphics.CompositingMode set to CompositingMode.SourceCopy? That should cause painting the background twice to be equivalent to painting it once, since it will replace the existing alpha/color data instead of compositing over it.

Kevin Gadd
Good suggestion, but when I set it to SourceCopy it kills any transparency and just draws an opaque black background.
Marc Charbonneau
I'm not certain there's any way to get the behavior you desire with pure WinForms. You could use P/Invoke to access the layered window APIs directly and set per-pixel alpha transparency for your window, but I'm not sure it's worth it.Have you considered using TransparencyKey to make the non-UI parts of your form show through, and then putting a partially opaque window behind it to create the desired effect?
Kevin Gadd
+2  A: 

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.

EDIT:

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.

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!

EDIT 2:

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....

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.

Good luck!

overslacked
I gave it a try (created a new Bitmap, created a Graphics from the image, filled it the same way as above, and draw it to the screen using the paint event's Graphics) and it had the same issue. It's not a bad idea though, is there any other way of drawing the image to the screen I could try?
Marc Charbonneau
I've updated my answer with something else to try; if you have any code you can send, it's the same username at gmail and I'll see if I can be of any help.
overslacked
Thanks, I'll give the double windows option a try and see if I can't make that work.
Marc Charbonneau
I ended up creating a second transparent background window and now I'm in business. Thanks for all the help!
Marc Charbonneau