C#で画面全体・アクティブウインドウのスクリーンショットを撮る方法

PrintscreenやAlt+Printscreenを利用しても、スクリーンショット撮ることはできますが、Frameworkの機能を使ってやってみます。なお、この方法は.NET Framework 2.0以降で使用可能です。

画面全体のスクリーンショットを撮る

Rectangle rect = Screen.PrimaryScreen.Bounds;
Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

using (Graphics g = Graphics.FromImage(bmp))
{
    g.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
}

bmp.Save(@"c:\test.png", ImageFormat.Png);

デュアルディスプレイなどで、ディスプレイが2枚以上ある場合には

//Before
Rectangle rect = Screen.PrimaryScreen.Bounds;
//After
Rectangle rect = Screen.AllScreens[1].Bounds;//PrimaryScreenが0となる

のように書けば良いでしょう。

アクティブウインドウのスクリーンショットを撮る

次に、アクティブウインドウのスクリーンショットを撮る方法です。まず、ホットキーなどで呼ばれるイベントを作成しておきましょう。
流れとしては、現在アクティブなウインドウのハンドルを取得し、そのウインドウの位置・大きさを取得、Graphics.CopyFromScreen。Win32 APIを直接使うため、関数を定義します。

[StructLayout(LayoutKind.Sequential, Pack = 4)]
private struct RECT
{
    public int left;
    public int top;
    public int right;
    public int bottom;
}

[DllImport("User32.Dll")]
static extern int GetWindowRect(IntPtr hWnd, out RECT rect);

[DllImport("user32.dll")]
extern static IntPtr GetForegroundWindow();
RECT r;
IntPtr active = GetForegroundWindow();
GetWindowRect(active, out r);
Rectangle rect = new Rectangle(r.left, r.top, r.right - r.left, r.bottom - r.top);

Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);

using (Graphics g = Graphics.FromImage(bmp))
{
    g.CopyFromScreen(rect.X, rect.Y, 0, 0, rect.Size, CopyPixelOperation.SourceCopy);
}

bmp.Save(@"c:\test.png", ImageFormat.Png);

それにしても.NETには他ウインドウを操作したり、情報を取得する方法がほとんど用意されてませんね。結局、APIを使うことがしばしば。