Capture screenshot of active window?

前端 未结 11 2228
春和景丽
春和景丽 2020-11-21 23:34

I am making a screen capturing application and everything is going fine. All I need to do is capture the active window and take a screenshot of this active window. Does an

相关标签:
11条回答
  • 2020-11-22 00:07

    Based on ArsenMkrt's reply, but this one allows you to capture a control in your form (I'm writing a tool for example that has a WebBrowser control in it and want to capture just its display). Note the use of PointToScreen method:

    //Project: WebCapture
    //Filename: ScreenshotUtils.cs
    //Author: George Birbilis (http://zoomicon.com)
    //Version: 20130820
    
    using System.Drawing;
    using System.Windows.Forms;
    
    namespace WebCapture
    {
      public static class ScreenshotUtils
      {
    
        public static Rectangle Offseted(this Rectangle r, Point p)
        {
          r.Offset(p);
          return r;
        }
    
        public static Bitmap GetScreenshot(this Control c)
        {
          return GetScreenshot(new Rectangle(c.PointToScreen(Point.Empty), c.Size));
        }
    
        public static Bitmap GetScreenshot(Rectangle bounds)
        {
          Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height);
          using (Graphics g = Graphics.FromImage(bitmap))
            g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
          return bitmap;
        }
    
        public const string DEFAULT_IMAGESAVEFILEDIALOG_TITLE = "Save image";
        public const string DEFAULT_IMAGESAVEFILEDIALOG_FILTER = "PNG Image (*.png)|*.png|JPEG Image (*.jpg)|*.jpg|Bitmap Image (*.bmp)|*.bmp|GIF Image (*.gif)|*.gif";
    
        public const string CUSTOMPLACES_COMPUTER = "0AC0837C-BBF8-452A-850D-79D08E667CA7";
        public const string CUSTOMPLACES_DESKTOP = "B4BFCC3A-DB2C-424C-B029-7FE99A87C641";
        public const string CUSTOMPLACES_DOCUMENTS = "FDD39AD0-238F-46AF-ADB4-6C85480369C7";
        public const string CUSTOMPLACES_PICTURES = "33E28130-4E1E-4676-835A-98395C3BC3BB";
        public const string CUSTOMPLACES_PUBLICPICTURES = "B6EBFB86-6907-413C-9AF7-4FC2ABF07CC5";
        public const string CUSTOMPLACES_RECENT = "AE50C081-EBD2-438A-8655-8A092E34987A";
    
        public static SaveFileDialog GetImageSaveFileDialog(
          string title = DEFAULT_IMAGESAVEFILEDIALOG_TITLE, 
          string filter = DEFAULT_IMAGESAVEFILEDIALOG_FILTER)
        {
          SaveFileDialog dialog = new SaveFileDialog();
    
          dialog.Title = title;
          dialog.Filter = filter;
    
    
          /* //this seems to throw error on Windows Server 2008 R2, must be for Windows Vista only
          dialog.CustomPlaces.Add(CUSTOMPLACES_COMPUTER);
          dialog.CustomPlaces.Add(CUSTOMPLACES_DESKTOP);
          dialog.CustomPlaces.Add(CUSTOMPLACES_DOCUMENTS);
          dialog.CustomPlaces.Add(CUSTOMPLACES_PICTURES);
          dialog.CustomPlaces.Add(CUSTOMPLACES_PUBLICPICTURES);
          dialog.CustomPlaces.Add(CUSTOMPLACES_RECENT);
          */
    
          return dialog;
        }
    
        public static void ShowSaveFileDialog(this Image image, IWin32Window owner = null)
        {
          using (SaveFileDialog dlg = GetImageSaveFileDialog())
            if (dlg.ShowDialog(owner) == DialogResult.OK)
              image.Save(dlg.FileName);
        }
    
      }
    }
    

    Having the Bitmap object you can just call Save on it

    private void btnCapture_Click(object sender, EventArgs e)
    {
      webBrowser.GetScreenshot().Save("C://test.jpg", ImageFormat.Jpeg);
    }
    

    The above assumes the GC will grab the bitmap, but maybe it's better to assign the result of someControl.getScreenshot() to a Bitmap variable, then dispose that variable manually when finished with each image, especially if you're doing this grabbing often (say you have a list of webpages you want to load and save screenshots of them):

    private void btnCapture_Click(object sender, EventArgs e)
    {
      Bitmap bitmap = webBrowser.GetScreenshot();
      bitmap.ShowSaveFileDialog();
      bitmap.Dispose(); //release bitmap resources
    }
    

    Even better, could employ a using clause, which has the added benefit of releasing the bitmap resources even in case of an exception occuring inside the using (child) block:

    private void btnCapture_Click(object sender, EventArgs e)
    {
      using(Bitmap bitmap = webBrowser.GetScreenshot())
        bitmap.ShowSaveFileDialog();
      //exit from using block will release bitmap resources even if exception occured
    }
    

    Update:

    Now WebCapture tool is ClickOnce-deployed (http://gallery.clipflair.net/WebCapture) from the web (also has nice autoupdate support thanks to ClickOnce) and you can find its source code at https://github.com/Zoomicon/ClipFlair/tree/master/Server/Tools/WebCapture

    0 讨论(0)
  • 2020-11-22 00:08

    Use the following code :

                // Shot size = screen size
                Size shotSize = Screen.PrimaryScreen.Bounds.Size;
    
                // the upper left point in the screen to start shot
                // 0,0 to get the shot from upper left point
                Point upperScreenPoint = new Point(0, 0);
    
                // the upper left point in the image to put the shot
                Point upperDestinationPoint = new Point(0, 0);
    
                // create image to get the shot in it
                Bitmap shot = new Bitmap(shotSize.Width, shotSize.Height);
    
                // new Graphics instance 
                Graphics graphics = Graphics.FromImage(shot);
    
                // get the shot by Graphics class 
                graphics.CopyFromScreen(upperScreenPoint, upperDestinationPoint, shotSize);
    
                // return the image
                pictureBox1.Image = shot;
    
    0 讨论(0)
  • 2020-11-22 00:09
    ScreenCapture sc = new ScreenCapture();
    // capture entire screen, and save it to a file
    Image img = sc.CaptureScreen();
    // display image in a Picture control named imageDisplay
    this.imageDisplay.Image = img;
    // capture this window, and save it
    sc.CaptureWindowToFile(this.Handle,"C:\\temp2.gif",ImageFormat.Gif);
    

    http://www.developerfusion.com/code/4630/capture-a-screen-shot/

    0 讨论(0)
  • 2020-11-22 00:12

    KvanTTT's code worked great. I extended it a bit to allow a little more flexibility on save format, as well as the ability to save by hWnd, .NET Control/Form. You can get a bitmap or save to file, with a few options.

    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Windows.Forms;
    
    namespace MosaiqPerformanceMonitor {
         public enum CaptureMode {
              Screen, Window
         }
    
         public static class ScreenCapturer {
              [DllImport("user32.dll")]
              private static extern IntPtr GetForegroundWindow();
    
              [DllImport("user32.dll")]
              private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
    
              [StructLayout(LayoutKind.Sequential)]
              private struct Rect {
                    public int Left;
                    public int Top;
                    public int Right;
                    public int Bottom;
              }
    
              [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
              public static extern IntPtr GetDesktopWindow();
    
              /// <summary> Capture Active Window, Desktop, Window or Control by hWnd or .NET Contro/Form and save it to a specified file.  </summary>
              /// <param name="filename">Filename.
              /// <para>* If extension is omitted, it's calculated from the type of file</para>
              /// <para>* If path is omitted, defaults to %TEMP%</para>
              /// <para>* Use %NOW% to put a timestamp in the filename</para></param>
              /// <param name="mode">Optional. The default value is CaptureMode.Window.</param>
              /// <param name="format">Optional file save mode.  Default is PNG</param>
              public static void CaptureAndSave(string filename, CaptureMode mode = CaptureMode.Window, ImageFormat format = null) {
                    ImageSave(filename, format, Capture(mode));
              }
    
              /// <summary> Capture a specific window (or control) and save it to a specified file.  </summary>
              /// <param name="filename">Filename.
              /// <para>* If extension is omitted, it's calculated from the type of file</para>
              /// <para>* If path is omitted, defaults to %TEMP%</para>
              /// <para>* Use %NOW% to put a timestamp in the filename</para></param>
              /// <param name="handle">hWnd (handle) of the window to capture</param>
              /// <param name="format">Optional file save mode.  Default is PNG</param>
              public static void CaptureAndSave(string filename, IntPtr handle, ImageFormat format = null) {
                    ImageSave(filename, format, Capture(handle));
              }
    
              /// <summary> Capture a specific window (or control) and save it to a specified file.  </summary>
              /// <param name="filename">Filename.
              /// <para>* If extension is omitted, it's calculated from the type of file</para>
              /// <para>* If path is omitted, defaults to %TEMP%</para>
              /// <para>* Use %NOW% to put a timestamp in the filename</para></param>
              /// <param name="c">Object to capture</param>
              /// <param name="format">Optional file save mode.  Default is PNG</param>
              public static void CaptureAndSave(string filename, Control c, ImageFormat format = null) {
                    ImageSave(filename, format, Capture(c));
              }
              /// <summary> Capture the active window (default) or the desktop and return it as a bitmap </summary>
              /// <param name="mode">Optional. The default value is CaptureMode.Window.</param>
              public static Bitmap Capture(CaptureMode mode = CaptureMode.Window) {
                    return Capture(mode == CaptureMode.Screen ? GetDesktopWindow() : GetForegroundWindow());
              }
    
              /// <summary> Capture a .NET Control, Form, UserControl, etc. </summary>
              /// <param name="c">Object to capture</param>
              /// <returns> Bitmap of control's area </returns>
              public static Bitmap Capture(Control c) {
                    return Capture(c.Handle);
              }
    
    
              /// <summary> Capture a specific window and return it as a bitmap </summary>
              /// <param name="handle">hWnd (handle) of the window to capture</param>
              public static Bitmap Capture(IntPtr handle) {
                    Rectangle bounds;
                    var rect = new Rect();
                    GetWindowRect(handle, ref rect);
                    bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
                    CursorPosition = new Point(Cursor.Position.X - rect.Left, Cursor.Position.Y - rect.Top);
    
                    var result = new Bitmap(bounds.Width, bounds.Height);
                    using (var g = Graphics.FromImage(result))
                         g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
    
                    return result;
              }
    
              /// <summary> Position of the cursor relative to the start of the capture </summary>
              public static Point CursorPosition;
    
    
              /// <summary> Save an image to a specific file </summary>
              /// <param name="filename">Filename.
              /// <para>* If extension is omitted, it's calculated from the type of file</para>
              /// <para>* If path is omitted, defaults to %TEMP%</para>
              /// <para>* Use %NOW% to put a timestamp in the filename</para></param>
              /// <param name="format">Optional file save mode.  Default is PNG</param>
              /// <param name="image">Image to save.  Usually a BitMap, but can be any
              /// Image.</param>
              static void ImageSave(string filename, ImageFormat format, Image image) {
                    format = format ?? ImageFormat.Png;
                    if (!filename.Contains("."))
                         filename = filename.Trim() + "." + format.ToString().ToLower();
    
                    if (!filename.Contains(@"\"))
                         filename = Path.Combine(Environment.GetEnvironmentVariable("TEMP") ?? @"C:\Temp", filename);
    
                    filename = filename.Replace("%NOW%", DateTime.Now.ToString("yyyy-MM-dd@hh.mm.ss"));
                    image.Save(filename, format);
              }
         }
    }
    
    0 讨论(0)
  • 2020-11-22 00:19

    I suggest next solution for capturing any current active window (not only our C# application) or entire screen with cursor position determination relative to left-top corner of window or screen respectively:

    public enum enmScreenCaptureMode
    {
        Screen,
        Window
    }
    
    class ScreenCapturer
    {
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
    
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);
    
        [StructLayout(LayoutKind.Sequential)]
        private struct Rect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
        }
    
        public Bitmap Capture(enmScreenCaptureMode screenCaptureMode = enmScreenCaptureMode.Window)
        {
            Rectangle bounds;
    
            if (screenCaptureMode == enmScreenCaptureMode.Screen)
            {
                bounds = Screen.GetBounds(Point.Empty);
                CursorPosition = Cursor.Position;
            }
            else
            {
                var foregroundWindowsHandle = GetForegroundWindow();
                var rect = new Rect();
                GetWindowRect(foregroundWindowsHandle, ref rect);
                bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
                CursorPosition = new Point(Cursor.Position.X - rect.Left, Cursor.Position.Y - rect.Top);
            }
    
            var result = new Bitmap(bounds.Width, bounds.Height);
    
            using (var g = Graphics.FromImage(result))
            {
                g.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
            }
    
            return result;
        }
    
        public Point CursorPosition
        {
            get;
            protected set;
        }
    }
    
    0 讨论(0)
  • 2020-11-22 00:19

    A little tweak to method static void ImageSave() will grant you the option where to save it. Credit goes to Microsoft (http://msdn.microsoft.com/en-us/library/sfezx97z.aspx)

    static void ImageSave(string filename, ImageFormat format, Image image, SaveFileDialog saveFileDialog1)
        { 
            saveFileDialog1.Filter = "JPeg Image|*.jpg|Bitmap Image|*.bmp|Gif Image|*.gif";
            saveFileDialog1.Title = "Enregistrer un image";
            saveFileDialog1.ShowDialog();
    
            // If the file name is not an empty string open it for saving.
            if (saveFileDialog1.FileName != "")
            {
                // Saves the Image via a FileStream created by the OpenFile method.
                System.IO.FileStream fs =
                   (System.IO.FileStream)saveFileDialog1.OpenFile();
                // Saves the Image in the appropriate ImageFormat based upon the
                // File type selected in the dialog box.
                // NOTE that the FilterIndex property is one-based.
                switch (saveFileDialog1.FilterIndex)
                {
                    case 1:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Jpeg);
                        break;
    
                    case 2:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Bmp);
                        break;
    
                    case 3:
                        image.Save(fs,
                           System.Drawing.Imaging.ImageFormat.Gif);
                        break;
                }
    
                fs.Close();
            }
    
    
    
        }
    

    Your button_click event should be coded something like this...

    private void btnScreenShot_Click(object sender, EventArgs e)
        {
    
            SaveFileDialog saveFileDialog1 = new SaveFileDialog();
    
    
            ScreenCapturer.CaptureAndSave(filename, mode, format, saveFileDialog1);
    
        }//
    
    0 讨论(0)
提交回复
热议问题