Capture screenshot of active window?

前端 未结 11 2233
春和景丽
春和景丽 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

提交回复
热议问题