2009-07-22 6 views
142

私はスクリーンキャプチャアプリケーションを作成していて、すべてうまくいっています。私がする必要があることは、アクティブなウィンドウをキャプチャし、このアクティブなウィンドウのスクリーンショットを撮ることだけです。私はこれをどのようにすることができるか誰にも分かりますか?アクティブなウィンドウのスクリーンショットをキャプチャしますか?

+14

を「アクティブなウィンドウは」YOURアプリやアプリが非表示になった場合にアクティブになり、ウィンドウのアクティブウィンドウを意味するのでしょうか? –

答えて

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

+5

私はすでに標準のスクリーンショットをキャプチャする方法を知っています。私はちょうどアクティブなウィンドウをキャプチャする方法を知る必要があります。 – user

+1

私は情報を変更しました – joe

+1

素晴らしい解決策!リンクありがとうございました。 –

179
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); 
} 
+0

ニート!私はWinAPIを使用する必要がありますが。これがMonoに実装されているかどうか知っていますか? –

+0

私はモノにしようとはしませんでしたが、フレームワークで正常に動作します –

+0

これはちょうど私に通常のスクリーンショットを与えます。 WinAPIを使用する必要はありませんか? – user

5

を捕捉するために、この質問からコードを使用することができます:How can I save a screenshot directly to a file in Windows?

ちょうどあなたがキャプチャしたいウィンドウのHandleプロパティにWIN32_API.GetDesktopWindow()を変更します。

21

Iは、それぞれ、ウィンドウまたは画面の左上隅にカーソル位置決意相対して任意の現在のアクティブウィンドウ(だけでなく、我々の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; 
    } 
} 
+0

System.Drawing.Rectangleを使用するのではなく、独自のRectangle構造体を宣言する必要があるのはなぜですか?属性を追加できるだけですか? Point構造についてもこれを行う必要があるかどうかは分かりますか? –

+0

@Alex、私は 'Rect'をシステム' Rectangle'で置き換えようとしましたが、その後 'GetWindowRect'関数が間違った長方形を返しました。 'Right'と' Top'の代わりに、出力矩形の 'Width'と' Height'を設定します。 –

+1

警告:フォアグラウンドウィンドウは、必ずしもこれが呼び出されるアプリケーションのウィンドウではありません。単一のウィンドウWPFアプリケーションの場合、 'var thisWindowHandle = new WindowInteropHelper(Application.Current.MainWindow).Handle;'を代わりに使用します – stijn

12

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("[email protected]")); 
       image.Save(filename, format); 
      } 
    } 
} 
+0

大きなリファクタリングスキル! –

+0

コードのトップビットは、それは問題なしで働いて、それはちょうど私が探していたものでした。共有していただきありがとうございます。 –

1

方法静的な無効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); 

    }// 
-1
をコード化する必要があります

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

    } 
} 

はあなただけ上記

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

それにSaveを呼び出すことができBitmapオブジェクトは、GCは、ビットマップをつかむだろうと仮定し、多分それは結果を代入する方が良いでしょう持ちますsomeControlのgetScreenshot()ビットマップ変数に、そして終了したときに、手動でその変数を配置、あなたが頻繁につかんこれをやっている場合は特に(あなたがそれらのスクリーンショットをロードして保存したいウェブページのリストを持っていると言う):

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

更新:

今WebCaptureツールはウェブから(http://gallery.clipflair.net/WebCapture)ClickOnceの配備であり、あなたがhttp://ClipFlair.codeplex.comでそのソースコードを見つけることができます(また、素敵な自動更新サポートのClickOnceのおかげを持っています)。

12

デスクトップまたはアクティブなウィンドウをキャプチャするためのスニペットです。 Windowsフォームへの参照はありません。

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

画面全体をキャプチャする方法:あなたが管理使用したい場合はhttp://www.snippetsource.net/Snippet/158/capture-screenshot-in-c

+0

この素晴らしいスニペットのために多くのクリスチャンに感謝します。それは私をたくさん助けました! – casaout

1

:もともとここで見つける

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

:アクティブウィンドウをキャプチャする方法

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

コード:これはProcessIdを介して任意のウィンドウをキャプチャします。

次のようにして、ウィンドウをアクティブにしました。

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

私はウィンドウをキャプチャするために印刷画面を使用しました。

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

次のコードを使用します。

  // 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; 
関連する問題