lunedì 17 gennaio 2011 #

Catturare lo schermo quando vi sono schermi multipli da C#

Oggi Stefano, ha fatto una domanda sul forum che sembrava molto semplice.

“Normalmente uso Screen.PrimaryScreen per catturare lo schermo da C# ma se ho più schermi collegati al pc come posso fare?”

La risposta era semplice, la classe screen ha una property AllScreens che è un array che ci da informazioni su tutti gli schermi connessi al PC, pertanto si può catturare semplicemente l’immagine di ogni schermo usando un ciclo for con il seguente codice:

                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;

Ma quello che voleva Stefano, era comporre una singola immagine con lo schermo completo, lo stesso che si ottiene usando un printscreen (STAMP), e questo non è affatto semplice.

Infatti, ho fatto un test usando 2 schermi (lui ne ha 4) usando il mio notebook, Windows Vista e Seven, (XP non ricordo se lo facesse), quando colleghi uno schermo secondario, ti permettono di posizionarlo da che lato vuoi rispetto al primario, modificando di conseguenza le property che indicano dove si trova lo schermo secondario rispetto al primario.

A causa di ciò, comporre un’immagine non è così semplice e richiede qualche calcolo, (ovviamente si può anche usare la clipboard volendo, ma essendo qui per imparare C# e .Net ci proviamo in altro modo).

Ecco che cosa ho fatto:

            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;
                        }
                    }

                }
            }

Basandomi sulla posizione dello schermo secondario, ho calcolato l’area dell’immagine composita e l’offset di posizionamento delle bitmap.

            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; }

Dopodiché compongo il bitmap sommando i due pezzi dello schermo. Sono certa c’è un modo migliore per farlo e ovviamente dovrete cambiare qualcosa per farlo funzionare con tre o più schermi. Se ci provate, fatemi sapere come avete risolto.

Technorati Tag: ,

 

per scaricare il codice Loggarsi e andare in Area Risorse

posted @ lunedì 17 gennaio 2011 19.55 | Feedback (0)

Copyright © Sabrina C.

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski