Today Stefano, a friend asked a question on our forum that looked very easy to answer.
“I Use Screen.PrimaryScreen to capture the screen in C# but I have a multiple screen environment (4 screens) and I need to capture them all. Any Ideas?”
The Answer was simple, Screen class has an AllScreens Property which is an array giving us all the screens connected to the PC, using that you can easily Capture Each screen image using a for cycle with the following code for each screen:
Bitmap ps = new Bitmap(x.Bounds.Width, x.Bounds.Height);
Graphics graphics = Graphics.FromImage(ps as Image);
graphics.CopyFromScreen(x.Bounds.X, x.Bounds.Y, 0, 0, x.Bounds.Size);
ps.Save(string.Format(@"c:\MultiImage{0}.jpg", i), ImageFormat.Jpeg);
this.textBox1.Text += string.Format("DONE <{0}> ", i) + Environment.NewLine;
But what He really wanted was a single image containing the whole screen, the same thing you obtain using a printscreen.
And that’s not so simple.
Infact, I made a test with 2 screens, using my notebook, and Windows Vista and 7 (I don’t remember if XP made the same), when you have multiple screens allows you to position the secondary screens on whatever side of your primary screen you desire, changing consequently the properties indicating where the secondary screen (or screens) are positioned based on the primary one.
Because of this, composing an image is not so easy and requires some calculations, (of course you can use the clipboard if you prefer, but we are here to learn C# and use .NET right?).
This is what I ended up with:
int width = 0;
int height = 0;
int minx = 0;
int miny = 0;
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
Screen z = Screen.AllScreens[i];
if (z.Bounds.X < minx) minx = z.Bounds.X;
if (z.Bounds.Y < miny) miny = z.Bounds.Y;
if (i == 0)
{
width = z.Bounds.Width;
height = z.Bounds.Height;
}
else
{
Screen p = Screen.AllScreens[i - 1];
//Sta a destra
if (z.Bounds.Right > p.Bounds.Right)
{
width += z.Bounds.Right - p.Bounds.Right;
}
else
{
//sta a sinistra
if (z.Bounds.Left < p.Bounds.Left)
{
width += Math.Abs(p.Bounds.Left - z.Bounds.Left);
}
}
//sta sopra
if (z.Bounds.Top < p.Bounds.Top)
{
height += (Math.Abs(z.Bounds.Top) - Math.Abs(z.Bounds.Bottom));
}
else
{
if (z.Bounds.Bottom > p.Bounds.Bottom)
{
height += z.Bounds.Bottom - p.Bounds.Bottom;
}
}
}
}
Based on the secondary screen position I’ve calculated the total image width and height and the offset of the bitmaps.
Bitmap ps = new Bitmap(width, height);
Graphics graphics = Graphics.FromImage(ps as Image);
this.textBox1.Text = "";
for (int i = 0; i < Screen.AllScreens.Length; i++)
{
Screen x = Screen.AllScreens[i];
this.textBox1.Text += string.Format("------------------->{0}<-------------------------", i)
+ Environment.NewLine;
this.textBox1.Text += "Top:" + x.Bounds.Top.ToString() + Environment.NewLine;
this.textBox1.Text += "Bottom:" + x.Bounds.Bottom.ToString() + Environment.NewLine;
this.textBox1.Text += "Left:" + x.Bounds.Left.ToString() + Environment.NewLine;
this.textBox1.Text += "Right:" + x.Bounds.Right.ToString() + Environment.NewLine;
this.textBox1.Text += "X:" + x.Bounds.X.ToString() + Environment.NewLine;
this.textBox1.Text += "Y:" + x.Bounds.Y.ToString() + Environment.NewLine;
this.textBox1.Text += "Width:" + x.Bounds.Width.ToString() + Environment.NewLine;
this.textBox1.Text += "Height:" + x.Bounds.Height.ToString() + Environment.NewLine;
this.textBox1.Text += string.Format("-------------------<{0}>-------------------------",
i) + Environment.NewLine;
graphics.CopyFromScreen(x.Bounds.X, x.Bounds.Y, x.Bounds.X + (Math.Abs(minx)),
x.Bounds.Y + Math.Abs(miny), x.Bounds.Size);
ps.Save(@"c:\SingleImage.jpg", ImageFormat.Jpeg);
this.textBox1.Text += string.Format("DONE <{0}> ", i) + Environment.NewLine;
}
Then I compose the bitmap joining the two pieces of screen. I’m sure there is a better way of doing it, and of course
You probably need to change some things to make it work with three or more screens.
If you try it, let me know.
Technorati Tag:
C#,
capture screen
To download the code, Log in and go to
resources area