Etkin pencerenin ekran görüntüsü yakalansın mı?


175

Bir ekran yakalama uygulaması yapıyorum ve her şey yolunda gidiyor. Tek yapmam gereken aktif pencereyi yakalamak ve bu aktif pencerenin ekran görüntüsünü almak. Bunu nasıl yapabileceğimi bilen var mı?


17
"Etkin pencere", uygulamanızın etkin penceresi veya uygulamanızın gizlenmesi durumunda etkin olacak pencere anlamına mı geliyor?
Corey Trager

Yanıtlar:


151
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/


7
Standart bir ekran görüntüsünü nasıl yakalayacağımı zaten biliyorum. Sadece aktif pencereyi nasıl yakalayacağımı bilmem gerekiyor.
user

3
Harika bir çözüm! Bağlantı için teşekkürler.
Matthew M.10

6
@ joe yukarıdaki kodu çalıştırmak çalışırken bir GDI + hata alıyorum. hata, görüntüleri kaydederken ScreenCpature sınıfında oluşur.
hurnhu

2
Mükemmel! Uygulamamdaki bir panelin içeriğini yakalamak istedim. Bu yüzden sc.CaptureWindowToFile (panel1.Handle, "c: \ temp.jpg", imageformat.jpg) ve voila!
D. Kermott

2
Yakınlaştırılmış Windows Arabirimi öğelerine sahip HD çözünürlükte bu sınıf tüm ekranı yakalamaz.
Yeronimo

223
Rectangle bounds = Screen.GetBounds(Point.Empty);
using(Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
{
    using(Graphics g = Graphics.FromImage(bitmap))
    {
         g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size);
    }
    bitmap.Save("test.jpg", ImageFormat.Jpeg);
}

geçerli pencere kullanımını yakalamak için

 Rectangle bounds = this.Bounds;
 using (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);
    }
    bitmap.Save("C://test.jpg", ImageFormat.Jpeg);
 }

Temiz! Ben WinAPI kullanmak zorunda kalacaktı. Bunun Mono'da uygulanıp uygulanmadığını biliyor musunuz?
Lucas Jones

Bu bana normal bir ekran görüntüsü veriyor. WinAPI'yi kullanmak zorunda değil miyim?
user

Merhaba vb web formu aspx ekran yakalama nasıl bilebilirim?
beny lim

Merhaba @benylim, şuna bir göz atın ( stackoverflow.com/questions/701798/… ) ve bu ( social.msdn.microsoft.com/Forums/en/netfxjscript/thread/… ), umarım bu yardımcı olur
Arsen Mkrtchyan

Isitz sadece java betiği ile yapabilir mi?
beny lim

29

Sırasıyla, pencerenin veya ekranın sol üst köşesine göre imleç konumu belirleme ile geçerli herhangi bir etkin pencereyi (yalnızca C # uygulamamızı değil) veya tüm ekranı yakalamak için bir sonraki çözüm öneririm:

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

Neden System.Drawing.Rectangle kullanmak yerine kendi Dikdörtgen yapımızı bildirmemiz gerekiyor? Sadece bir özellik ekleyebilmemiz için mi? Bunu Nokta yapısı için de yapmamız gerekip gerekmediğini biliyor musunuz?
Caster Troy

@Alex kızkardeşimi yerine çalıştı RectSistemi ile Rectangle, ama bundan sonra fonksiyon GetWindowRectyanlış dikdörtgen döndü. Yerine Rightve Topbu set Widthve Heightçıkış dikdörtgenin.
Ivan Kochurkin

1
Bir uyarı: Ön plan penceresi, bunun çağrıldığı uygulamanın penceresi değildir. var thisWindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;Bunun yerine tek bir pencere WPF uygulaması için kullanabilirsiniz
stijn

23

İşte masaüstünü veya etkin pencereyi yakalamak için bir snippet. Windows Forms'a başvurusu yoktur.

public class ScreenCapture
{
    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    public static extern IntPtr GetDesktopWindow();

    [StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }   

    [DllImport("user32.dll")]
    private static extern IntPtr GetWindowRect(IntPtr hWnd, ref Rect rect);

    public static Image CaptureDesktop()
    {
        return CaptureWindow(GetDesktopWindow());
    }

    public static Bitmap CaptureActiveWindow()
    {
        return CaptureWindow(GetForegroundWindow());
    }

    public static Bitmap CaptureWindow(IntPtr handle)
    {
        var rect = new Rect();
        GetWindowRect(handle, ref rect);
        var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
        var result = new Bitmap(bounds.Width, bounds.Height);

        using (var graphics = Graphics.FromImage(result))
        {
            graphics.CopyFromScreen(new Point(bounds.Left, bounds.Top), Point.Empty, bounds.Size);
        }

        return result;
    }
}

Tüm ekran nasıl yakalanır:

var image = ScreenCapture.CaptureDesktop();
image.Save(@"C:\temp\snippetsource.jpg", ImageFormat.Jpeg);

Etkin pencereyi yakalama:

var image = ScreenCapture.CaptureActiveWindow();
image.Save(@"C:\temp\snippetsource.jpg", ImageFormat.Jpeg);

Başlangıçta burada bulundu: http://www.snippetsource.net/Snippet/158/capture-screenshot-in-c


Bu harika pasaj için çok teşekkürler Christian. Bana çok yardımcı oldu!
casaout

Bu harika çalışıyor ancak kullanıcı bu ekranda ölçekleme
ayarına sahipse işe yaramaz

12

KvanTTT'nin kodu harika çalıştı. HWnd, .NET Control / Form ile kaydetme yeteneğinin yanı sıra kaydetme biçiminde biraz daha fazla esneklik sağlamak için biraz uzattım. Birkaç seçenekle bir bitmap alabilir veya dosyaya kaydedebilirsiniz.

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

Mükemmel refactory becerileri!
Ahmed Alejo

Kod üst bit, hiçbir sorun ile çalışma var ve sadece ne aradığını oldu. Paylaşım için teşekkürler.
Hugo Yates



1

Statik void ImageSave () yönteminde küçük bir değişiklik, size nereye kaydedileceği seçeneğini verecektir. Kredi Microsoft'a gidiyor (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();
        }



    }

Button_click etkinliğiniz böyle bir şeyle kodlanmalıdır ...

private void btnScreenShot_Click(object sender, EventArgs e)
    {

        SaveFileDialog saveFileDialog1 = new SaveFileDialog();


        ScreenCapturer.CaptureAndSave(filename, mode, format, saveFileDialog1);

    }//

1

Yönetilen kod kullanmak istiyorsanız: Bu işlem ProcessId aracılığıyla herhangi bir pencereyi yakalar.

Pencereyi aktif hale getirmek için aşağıdakileri kullandım.

Microsoft.VisualBasic.Interaction.AppActivate(ProcessId);
Threading.Thread.Sleep(20);

Bir ekranı yakalamak için yazdırma ekranını kullandım.

SendKeys.SendWait("%{PRTSC}");
Threading.Thread.Sleep(40);
IDataObject objData = Clipboard.GetDataObject();

1

Aşağıdaki kodu kullanın:

            // 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

ArsenMkrt'ın cevabına dayanarak, ancak bu, formunuzdaki bir kontrolü yakalamanızı sağlar (örneğin, içinde bir WebBrowser kontrolü olan ve sadece görüntüsünü yakalamak isteyen bir araç yazıyorum). PointToScreen yönteminin kullanımına dikkat edin:

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

  }
}

Bitmap nesnesine sahip olmak için Kaydet'i çağırabilirsiniz

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

Yukarıdaki, GC'nin bitmap'i ele alacağını varsayar, ancak belki bazıControl.getScreenshot () sonucunu bir Bitmap değişkenine atamak daha iyidir, daha sonra her bir görüntü ile işiniz bittiğinde bu değişkeni manuel olarak atın (özellikle bu sıkma işlemini sık sık yapıyorsanız ( yüklemek ve kaydetmek istediğiniz web sayfalarının bir listeniz olduğunu varsayalım):

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

Daha da iyisi, using (child) bloğunun içinde bir istisna olsa bile bitmap kaynaklarını serbest bırakmanın ek yararına sahip bir kullanma cümlesi kullanabilir:

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
}

Güncelleme:

Artık WebCapture aracı web'den ClickOnce tarafından dağıtılır ( http://gallery.clipflair.net/WebCapture ) (ayrıca ClickOnce sayesinde güzel bir otomatik güncelleme desteği vardır) ve kaynak kodunu https://github.com/Zoomicon adresinde bulabilirsiniz. / ClipFlair / ağaç / ana / Sunucu / Araçlar / WebCapture

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.