Захват скриншота активного окна?
Я делаю приложение для захвата экрана, и все идет хорошо. Все, что мне нужно сделать, это захватить активное окно и сделать скриншот активного окна. Кто-нибудь знает как я могу это сделать?
11 ответов:
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/
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); }
для захвата текущего окна используйте
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); }
Я предлагаю следующее решение для захвата любого текущего активного окна (не только нашего приложения C#) или всего экрана с определением положения курсора относительно левого верхнего угла окна или экрана соответственно:
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; } }
вот фрагмент для захвата рабочего стола или активного окна. Он не имеет ссылки на Windows Forms.
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; } }
как захватить весь экран:
var image = ScreenCapture.CaptureDesktop(); image.Save(@"C:\temp\snippetsource.jpg", ImageFormat.Jpeg);
как захватить активное окно:
var image = ScreenCapture.CaptureActiveWindow(); image.Save(@"C:\temp\snippetsource.jpg", ImageFormat.Jpeg);
первоначально найдено здесь:http://www.snippetsource.net/Snippet/158/capture-screenshot-in-c
KvanTTT работал отлично. Я немного расширил его, чтобы позволить немного больше гибкости в формате сохранения, а также возможность сохранения с помощью hWnd, .NET Control/Form. Вы можете получить растровое изображение или сохранить в файл, с несколько вариантов.
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); } } }
Я предполагаю, что вы используете
Graphics.CopyFromScreen
чтобы получить скриншот.можно использовать P / Invoke to GetForegroundWindow (а затем получить его положение и размер), чтобы определить, из какого региона вам нужно скопировать.
вы можете использовать код из этого вопрос: Как я могу сохранить скриншот непосредственно в файл в Windows?
просто изменить
WIN32_API.GetDesktopWindow()
к свойству Handle окна, которое вы хотите захватить.
немного подправить метод static void ImageSave () предоставит вам возможность, где его сохранить. Кредит идет в 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(); } }
ваше событие button_click должно быть закодировано примерно так...
private void btnScreenShot_Click(object sender, EventArgs e) { SaveFileDialog saveFileDialog1 = new SaveFileDialog(); ScreenCapturer.CaptureAndSave(filename, mode, format, saveFileDialog1); }//
Если вы хотите использовать управляемый код: это захватит любое окно через ProcessId.
я использовал следующее, чтобы сделать окно активным.
Microsoft.VisualBasic.Interaction.AppActivate(ProcessId); Threading.Thread.Sleep(20);
я использовал экран печати для захвата окна.
SendKeys.SendWait("%{PRTSC}"); Threading.Thread.Sleep(40); IDataObject objData = Clipboard.GetDataObject();
использовать следующий код :
// 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;
на основе ответа ArsenMkrt, но это позволяет вам захватить элемент управления в вашей форме (я пишу инструмент, например, который имеет элемент управления WebBrowser в нем и хочет захватить только его отображение). Обратите внимание на использование метода PointToScreen:
//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); } } }
имея растровый объект, вы можете просто вызвать Save на нем
private void btnCapture_Click(object sender, EventArgs e) { webBrowser.GetScreenshot().Save("C://test.jpg", ImageFormat.Jpeg); }
выше предполагается, что GC захватит растровое изображение, но, возможно, лучше назначить результат someControl.getScreenshot () в растровую переменную, затем утилизируйте эту переменную вручную, когда закончите, особенно если вы часто это делаете (скажем, у вас есть список веб-страниц, которые вы хотите загрузить и сохранить скриншоты из них):
private void btnCapture_Click(object sender, EventArgs e) { Bitmap bitmap = webBrowser.GetScreenshot(); bitmap.ShowSaveFileDialog(); bitmap.Dispose(); //release bitmap resources }
обновление:
Теперь WebCapture инструмент ClickOnce-развернуты (http://gallery.clipflair.net/WebCapture) из интернета (также имеет хорошую поддержку автозапуска благодаря ClickOnce), и вы можете найти его исходный код на http://ClipFlair.codeplex.com.