Introduction
So, I got the idea in my head the other day that i really wanted the background of the form for one of my projects to be translucent. Unfortunately, this isn't built into .NET 2.0. It seems like it's a part of .NET 3.0, but I haven't evolved that far yet, so I had to do it on my own. Anyways, after a while, I got something working, and here it is.
As you can see from the picture, it's pretty awesome. I put a button and a DateTime picker on the sample app for some reason! Oh, that's so you can see that unlike setting the Opacity value for the form, with this form, the controls on top of the form don't get their Opacity modified.
Background
At first, I got really excited because I found that the Form
class has an Opacity
member. Then, when I tried to use Opacity
to get what I wanted, I was sad. I was sad because setting this value to say 50 percent means that every control on the form is also 50 percent opaque. That's not what I wanted at all!
Using the code
The code's pretty simple to use. You know when you start a new Windows Forms project and it makes a file called Form1.cs? To use this code, all you need to do is make Form1
inherit from AwesomeForm
instead of System.Windows.Forms.Form
. Well, that and make sure the compiler can find my code. If you don't know what this means, look in the sample code. It's pretty straightforward.
How does it work?
Many people are already convinced I'm a genius for figuring out how to do this using only GDI+. Unfortunately, I'm not a genius, I just had the idea and found some good code samples.
The first code sample I'd like to point out, is Google Talk styled Windows Form, which got me thinking about making my own Form
. It's a much more complete project than this one, so if you're looking for that kind of thing, I highly recommend it. Yeah, I know, mine doesn't even have a maximize button. Maybe one day...
Probably the most useful code sample I found was from tommy.blog. Anybody who has tried to figure out how to do a screen capture using .NET has seen a lot of annoying Interop code for something that ought to be really simple. Well, here's how simple it can be:
g.CopyFromScreen(this.Left, region.Top, 0, 0, region.Size);
Wow! That takes one line of C# code! No Interop, the only thing you need is a Graphics
object and an area that you want to capture!
So, below is the code that I use to get the contents of the screen that are underneath my form. It's pretty simple, and based on the above method of capturing the screen, but there's one trick. Can you spot it?
private Bitmap GetBackground()
{
Bitmap rval = new Bitmap(this.Width, this.Height);
Graphics g = Graphics.FromImage(rval);
Point loc = this.Location;
this.Opacity = 0;
g.CopyFromScreen(loc.X, loc.Y, 0, 0, rval.Size);
this.Opacity = 1;
using (SolidBrush sb = new SolidBrush(Color.FromArgb(208, this.BackColor)))
g.FillRectangle(sb, new Rectangle(0, 0, rval.Width, rval.Height));
return rval;
}
That's right, to get what's underneath the form, we have to hide the form first! I did this by setting the Form
's
opacity to 0, making it completely transparent, taking the screenshot and then setting it back to 1. My first idea was to set it to Visible = false
, but that's obviously a bad idea. The program disappears from the taskbar which is annoying, and it makes dragging the form impossible, since every time the form gets redrawn it becomes invisible, cancelling the drag action.
If you want to use this code inside a regular Form
, it'll work, but you have to do a little fudging with the numbers to get it to look right. I use loc
as the location I want to take the screen grab at, and I can use the form's location for it because I'm using a borderless Form
. If you use a regular one, this isn't going to work. I feel kind of like I'm missing something dumb here, but I wasn't that worried about it since I'm not using this in a regular form.
Issues
There are a few performance issues right now. That's OK though, since this is the first version, and I started it today. The most obvious problem is that it's a little slow to update when you drag the window around the desktop, but it's not too bad. Also, I haven't implemented any kind of redraw when then contents of the screen behind the window change independent of the window. So, like if you minimized a window that was beneath this one, this window will still have that window's contents in it until it decides to redraw itself.