Make .NET snipping tool compatible with multiple monitors

后端 未结 5 2028
轮回少年
轮回少年 2021-01-06 18:54

An alternative snipping tool solution was provided in this posting: .NET Equivalent of Snipping Tool

Now it\'s necessary to make it work for selected screens (on mul

5条回答
  •  爱一瞬间的悲伤
    2021-01-06 19:27

    I have create the helper class to capture the selected area on specific screen where control reside. It works on multiple screens.

    Displays

    The idea is taken from multiple online resources that basically Freeze the Screen and put into PictureBox .NET control.

    Here's the codes:

    public class CaptureScreen : IDisposable
    {
        readonly Control control;
        readonly Pen penSelectedAreaScreenShot;
    
        Form frmPictureBox = null;
        PictureBox pictureBoxScreenShot = null;
        Point selectedScreenShotStartPoint;
        Size selectedScreenShotSize;
        bool isMouseDownSelectedScreenShot = false;
    
        public event Action SelectedScreenAreaCaptured;
    
        public event Action ScreenCaptureFailed;
    
        public CaptureScreen(Control control)
        {
            if (control == null)
            {
                throw new ArgumentNullException("control");
            }
    
            this.control = control;
    
            this.penSelectedAreaScreenShot = new Pen(Color.Red, 1);
            this.penSelectedAreaScreenShot.DashStyle = DashStyle.Dot;
        }
    
        public void BeginStart()
        {
            #region Setup the Picture Box for ScreenShot
    
            if (this.frmPictureBox != null)
            {
                this.frmPictureBox.Close();
                this.frmPictureBox.Dispose();
                this.frmPictureBox = null;
            }
    
            if (this.pictureBoxScreenShot != null)
            {
                this.pictureBoxScreenShot.Dispose();
                this.pictureBoxScreenShot = null;
            }
    
            this.frmPictureBox = new Form
            {
                BackColor = Color.Black,
                Cursor = Cursors.Cross,
                FormBorderStyle = FormBorderStyle.None,
                StartPosition = FormStartPosition.CenterParent,
                TopLevel = true,
                TopMost = true,
                Top = 0,
                Left = 0,
                WindowState = FormWindowState.Maximized,
                KeyPreview = true
            };
    
            this.pictureBoxScreenShot = new PictureBox
            {
                Location = new Point(0, 0),
                SizeMode = PictureBoxSizeMode.Zoom
            };
            this.frmPictureBox.Controls.Add(this.pictureBoxScreenShot);
    
            #endregion
    
            #region Capture the Screen
    
            Bitmap screenShotBitmap = null;
            Graphics graphics = null;
            MemoryStream stream = null;
            try
            {
                Screen currentScreen = Screen.FromControl(this.control);
    
                screenShotBitmap = new Bitmap(currentScreen.Bounds.Width, currentScreen.Bounds.Height);
    
                graphics = Graphics.FromImage(screenShotBitmap as Image);
                graphics.CopyFromScreen(currentScreen.Bounds.X, currentScreen.Bounds.Y, 0, 0, screenShotBitmap.Size);
    
                stream = new MemoryStream();
                screenShotBitmap.Save(stream, ImageFormat.Png);
    
                this.pictureBoxScreenShot.Size = screenShotBitmap.Size;
                this.pictureBoxScreenShot.Image = Image.FromStream(stream);
            }
            catch (Exception ex)
            {
                if (this.ScreenCaptureFailed != null)
                {
                    this.ScreenCaptureFailed(this, ex);
                }
            }
            finally
            {
                if (stream != null)
                {
                    stream.Close();
                    stream.Dispose();
                    stream = null;
                }
    
                if (graphics != null)
                {
                    graphics.Dispose();
                    graphics = null;
                }
    
                if (screenShotBitmap != null)
                {
                    screenShotBitmap.Dispose();
                    screenShotBitmap = null;
                }
            }
    
            #endregion
    
            this.frmPictureBox.KeyDown += this.frmPictureBox_KeyDown;
    
            this.pictureBoxScreenShot.MouseMove += this.pictureBoxScreenShot_MouseMove;
            this.pictureBoxScreenShot.MouseDown += this.pictureBoxScreenShot_MouseDown;
            this.pictureBoxScreenShot.MouseUp += this.pictureBoxScreenShot_MouseUp;
    
            this.frmPictureBox.Show(this.control);
        }
    
        public void Exit()
        {
            if (this.frmPictureBox != null)
            {
                this.frmPictureBox.Close();
                this.frmPictureBox.Dispose();
                this.frmPictureBox = null;
            }
    
            if (this.pictureBoxScreenShot != null)
            {
                this.pictureBoxScreenShot.Dispose();
                this.pictureBoxScreenShot = null;
            }
    
            this.isMouseDownSelectedScreenShot = false;
        }
    
        [DebuggerStepThrough]
        void frmPictureBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Escape)
            {
                this.Exit();
            }
        }
    
        void pictureBoxScreenShot_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.pictureBoxScreenShot.Image == null)
            {
                this.Exit();
                return;
            }
    
            if (this.isMouseDownSelectedScreenShot)
            {
                this.pictureBoxScreenShot.Refresh();
    
                this.selectedScreenShotSize = new Size(
                    e.X - this.selectedScreenShotStartPoint.X,
                    e.Y - this.selectedScreenShotStartPoint.Y);
    
                // Draw the selected area rectangle.
                this.pictureBoxScreenShot.CreateGraphics().DrawRectangle(this.penSelectedAreaScreenShot,
                    this.selectedScreenShotStartPoint.X, this.selectedScreenShotStartPoint.Y,
                    this.selectedScreenShotSize.Width, this.selectedScreenShotSize.Height);
            }
        }
    
        void pictureBoxScreenShot_MouseDown(object sender, MouseEventArgs e)
        {
            if (!this.isMouseDownSelectedScreenShot)
            {
                if (e.Button == MouseButtons.Left)
                {
                    this.selectedScreenShotStartPoint = new Point(e.X, e.Y);
                }
    
                this.pictureBoxScreenShot.Refresh();
    
                this.isMouseDownSelectedScreenShot = true;
            }
        }
    
        void pictureBoxScreenShot_MouseUp(object sender, MouseEventArgs e)
        {
            if (this.pictureBoxScreenShot.Image == null)
            {
                this.Exit();
                return;
            }
    
            isMouseDownSelectedScreenShot = false;
    
            this.frmPictureBox.Hide();
    
            // Check whether there is something get selected.
            if (this.selectedScreenShotSize.Width > 0 && this.selectedScreenShotSize.Height > 0)
            {
                Bitmap selectedAreaBitmap = null;
                Graphics graphics = null;
                Bitmap screenShotBitmap = null;
    
                try
                {
                    selectedAreaBitmap = new Bitmap(this.selectedScreenShotSize.Width, this.selectedScreenShotSize.Height);
    
                    graphics = Graphics.FromImage(selectedAreaBitmap);
    
                    graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
                    graphics.CompositingQuality = CompositingQuality.HighQuality;
    
                    screenShotBitmap = new Bitmap(this.pictureBoxScreenShot.Image, this.pictureBoxScreenShot.Size);
                    graphics.DrawImage(screenShotBitmap, 0, 0, new Rectangle(this.selectedScreenShotStartPoint, this.selectedScreenShotSize), GraphicsUnit.Pixel);
    
                    if (this.SelectedScreenAreaCaptured != null)
                    {
                        this.SelectedScreenAreaCaptured(this, selectedAreaBitmap);
                    }
                    else
                    {
                        Clipboard.SetImage(selectedAreaBitmap);
                        MessageBox.Show(this.control, "Selected Screen is copied to Clipboard.");
                    }
                }
                catch (Exception ex)
                {
                    if (this.ScreenCaptureFailed != null)
                    {
                        this.ScreenCaptureFailed(this, ex);
                    }
                }
                finally
                {
                    if (screenShotBitmap != null)
                    {
                        screenShotBitmap.Dispose();
                        screenShotBitmap = null;
                    }
    
                    if (graphics != null)
                    {
                        graphics.Dispose();
                        graphics = null;
                    }
    
                    if (selectedAreaBitmap != null)
                    {
                        selectedAreaBitmap.Dispose();
                        selectedAreaBitmap = null;
                    }
                }
            }
    
            this.Exit();
        }
    
        #region IDisposable Member
    
        public void Dispose()
        {
            try
            {
                this.Exit();
            }
            catch { }
        }
    
        #endregion
    
    }
    

    And you can use it like this:

       CaptureScreen captureScreen = new CaptureScreen(this);
    
       // If event not implement, then by default it will copied to clipboard.
       //captureScreen.SelectedScreenAreaCaptured += delegate(object am_sender, Bitmap am_selectedAreaBitmap)
       //{
            //string destFilename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), String.Format("Capture_{0}.png", DateTime.Now.ToString("yyyyMMddHHmmss")));
            //am_selectedAreaBitmap.Save(destFilename, System.Drawing.Imaging.ImageFormat.Png);                
       //};
    
       // Implements this to handle the exception that occurs during screen capture.
       //captureScreen.ScreenCaptureFailed += delegate(object am_sender, Exception am_ex)
       //{
            //MessageBox.Show(this, am_ex.Message, "Unable to Capture the Screen", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
       //};
    
       captureScreen.BeginStart();
    

提交回复
热议问题