Screen Capture

現在表示中の Screen を Capture して画像ファイル(gif 形式)に保存します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 一般的に Screen を Capture して画像ファイルに保存する手順は次のようになります。
    1. Capture するウインドウ(画面)を表示します。
    2. Print Screen キーを押してクリップボードに格納します。
    3. 画像編集ツールなどを起動して、クリップボードから張り付けます。
    4. ファイル名を指定して保存します。
    この手順は結構面倒で急ぎのときには間に合わず、連続してキャプチャーすることが出来ません。
    そこで久しぶりにC#で簡単に Capture できるプログラムを開発することにしました。
    2015/07/07 現在の開発環境は Windows 8.1 & Visual Studio 2005 です。
    開発環境によっては動かないことがあるので注意して下さい。
    【Windows10 では Print Screen キーを押すと「OneDrive\画像\スクリーンショット」のフォルダーに PNG 形式で保存されるようになりました。】
  2. g.CopyFromScreen を使って Bitmap を取得するプログラムです。
    //using System.Drawing;
    //using System.Windows.Forms;
    
    //Bitmapの作成
    Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
        Screen.PrimaryScreen.Bounds.Height);
    //Graphicsの作成
    Graphics g = Graphics.FromImage(bmp);
    //画面全体をコピーする
    g.CopyFromScreen(new Point(0, 0), new Point(0, 0), bmp.Size);
    //解放
    g.Dispose();
    
    //表示
    PictureBox1.Image = bmp;
    
  3. Bitmap bmp が取得出来れば、画像を保存するのは簡単なのですが。 (^_^;)
    ところが、残念ながら私の現在の環境ではコンパイルエラーで動きませんでした。
    画面をキャプチャする の説明では動くはずなのですが、 どこかミスっているのでしょうか? (;_;)
    画像の保存は Draw で書いたイメージをファイルに出力 を参照して下さい。
    アプリケーションプログラムの中に現在の画面を保存する機能を組み込むのは簡単です。
    現在の画面の保存は MP4, AVI Capture を参照して下さい。

Win32 API を使用

  1. g.CopyFromScreen が使えないので Win32 API を使って Screen を Capture するプログラムを作成します。
    プロジェクトの構築は [Visual C#プロジェクト] から [空のプロジェクト] を選びます。
    プロジェクトに格納するファイルは Console.csproj と Console.cs だけです。
    詳細は Hello C# (C# Console Mode)を参照して下さい。
  2. プログラムの最初に、次の using を定義して下さい。
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
  3. ソリューション・エクスプローラで「参照設定」を右クリックし「参照の追加」を選択します。
    System.Drawing.dll を追加して下さい。
    System.Windows.Forms を追加して下さい。
  4. Win32 API で Screen を Capture して画像ファイルに保存するプログラムです。
    Console.cs の名前でプロジェクトに格納して下さい。
    /*****************************************/
    /*★ Screen を Capture する    前田 稔 ★*/
    /*****************************************/
    using System;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Windows.Forms;
    using System.Runtime.InteropServices;
    
    class ConsoleMode
    {
        private  const int SRCCOPY = 13369376;
        private  const int CAPTUREBLT = 1073741824;
        private  const int SW_HIDE = 0;
    
        [DllImport("user32.dll")]
        private  static extern IntPtr GetDC(IntPtr hwnd);
    
        [DllImport("gdi32.dll")]
        private  static extern int BitBlt(IntPtr hDestDC,
            int x, int y, int nWidth, int nHeight,
            IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);
    
        [DllImport("user32.dll")]
        private  static extern IntPtr ReleaseDC(IntPtr hwnd, IntPtr hdc);
    
        [DllImport("user32.dll")]
        private static extern IntPtr GetWindowDC(IntPtr hwnd);
    
        [DllImport("user32.dll")]
        private static extern IntPtr GetForegroundWindow();
    
        [DllImport("user32.dll")]
        private static extern int GetWindowRect(IntPtr hwnd, ref  RECT lpRect);
    
        [DllImport("user32.dll")]
        private static extern int ShowWindow(IntPtr handle, int command);
    
        [StructLayout(LayoutKind.Sequential)]
        private struct RECT 
        {
            public int left;
            public int top;
            public int right;
            public int bottom;
        }
    
        /// <summary>
        /// プライマリスクリーンの画像を取得する
        /// </summary>
        /// <returns>プライマリスクリーンの画像</returns>
        public static Bitmap CaptureScreen()
        {
            IntPtr hWndHide = GetForegroundWindow();
            //プライマリモニタのデバイスコンテキストを取得
            IntPtr disDC = GetDC(IntPtr.Zero);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                Screen.PrimaryScreen.Bounds.Height);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();
            //この Window を隠す
            ShowWindow(hWndHide, SW_HIDE);
            System.Threading.Thread.Sleep(500);
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height, disDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(IntPtr.Zero, disDC);
    
            return bmp;
        }
    
        /// <summary>
        /// アクティブなウィンドウの画像を取得する
        /// </summary>
        /// <returns>アクティブなウィンドウの画像</returns>
        public static Bitmap CaptureActiveWindow()
        {
            //アクティブなウィンドウのデバイスコンテキストを取得
            IntPtr hWnd = GetForegroundWindow();
            IntPtr winDC = GetWindowDC(hWnd);
            //ウィンドウの大きさを取得
            RECT winRect = new RECT();
            GetWindowRect(hWnd, ref winRect);
            //Bitmapの作成
            Bitmap bmp = new Bitmap(winRect.right - winRect.left,
                winRect.bottom - winRect.top);
            //Graphicsの作成
            Graphics g = Graphics.FromImage(bmp);
            //Graphicsのデバイスコンテキストを取得
            IntPtr hDC = g.GetHdc();
            //Bitmapに画像をコピーする
            BitBlt(hDC, 0, 0, bmp.Width, bmp.Height, winDC, 0, 0, SRCCOPY);
            //解放
            g.ReleaseHdc(hDC);
            g.Dispose();
            ReleaseDC(hWnd, winDC);
    
            return bmp;
        }
    
        public static int Main()
        {
            long    nowTime = DateTime.Now.Ticks/1000000;
            string  str = "c:\\tmp\\s" + nowTime.ToString() + ".gif";
            Bitmap bmp = CaptureScreen();
            bmp.Save(str, ImageFormat.Gif);
            return 0;
        }
    }
    
  5. Win32 API の説明は「超初心者のプログラム入門(C言語 Windows)」を参照して下さい。
    保存する画像ファイルの名前は、連続して何度でも実行出来るようにタイマーを使って生成します。
    str がファイル名で "c:\\tmp\\" のフォルダーに格納します。
        long    nowTime = DateTime.Now.Ticks/1000000;
        string  str = "c:\\tmp\\s" + nowTime.ToString() + ".gif";
    
  6. 保存する画像ファイルのサイズは new Bitmap() で設定して下さい。
    例えば 1920*1080 に広げるときは、次のようになります。
        //Bitmap bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
        //    Screen.PrimaryScreen.Bounds.Height);
        Bitmap bmp = new Bitmap(1920, 1080);
    
  7. CaptureScreen() では Window を SW_HIDE で隠してキャプチャーします。
    従ってキャプチャープログラムに邪魔されること無く、現在の画面を取得出来ます。
    これに対して CaptureActiveWindow() はアクティブなウィンドウをキャプチャーする関数です。
    こちらを使うと SW_HIDE を使わないでキャプチャーするので試して下さい。
  8. クリップボードを使って Copy&Paste するプログラムは Clipboard Image を参照して下さい。
    Windows(C++) でもクリップボードのプログラムを作成しています。
    全画面をクリップボードにコピーする クリップボードの画像を描画 を参照して下さい。

超初心者のプログラム入門(C# Frame Work)