Ctrl+PrintScreen でアクティブなウィンドウをキャプチャする

手順書などを作るために画面のキャプチャをする時に、Alt+PrintScreen でアクティブな画面をキャプチャします。
が、メニューをキャプチャしたいときに【Alt】キーを押すと、そのメニューが消えてしまうんですよね。

なので、各種ツールを探すんですが…Ctrl+PrintScreen に割り当てればいいんじゃないの?ということで自作します。
Ctrl キーの場合は、メニューが閉じられませんからね。

こんな感じで、手軽にメニューもキャプチャできます。

■アクティブウィンドウのキャプチャ

using System.Runtime.InteropServices;

[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 GetWindowDC(IntPtr hwnd);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern int GetWindowRect(IntPtr hwnd, ref  RECT lpRect);
private const int SRCCOPY = 13369376;
[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);

///
/// アクティブウィンドウをキャプチャ
///
///
private Bitmap ActiveWindowCapture()
{
    IntPtr hWnd = GetForegroundWindow();
    IntPtr hDC = GetWindowDC(hWnd);
    //ウィンドウの大きさを取得
    RECT rect = new RECT();
    GetWindowRect(hWnd, ref rect);
    Bitmap bmp = new Bitmap(rect.right - rect.left, rect.bottom - rect.top);
    Graphics g = Graphics.FromImage(bmp);
    IntPtr gDC = g.GetHdc();
    BitBlt(gDC, 0, 0, bmp.Width, bmp.Height, hDC, 0, 0, SRCCOPY);
    g.ReleaseHdc(gDC);
    g.Dispose();
    ReleaseDC(hWnd, hDC);
    return bmp;
}

win api を多用しないといけないので、DllImport が多いですが、こんな感じ。
# BitBlt とか使いたくないけど、他にいい方法がありませんかね?

■ホットキーの登録/解除

ホットキーは、RegisterHotKey と UnregisterHotKey を使います。
HOTKEY_ID のほうは、他のアプリケーションとダブらないように適当に変えてください。

// 
[DllImport("user32.dll")]
extern static int RegisterHotKey(IntPtr hWnd, int id, int modKey, int key);
[DllImport("user32.dll")]
extern static int UnregisterHotKey(IntPtr hWnd, int id);
const int MOD_ALT = 0x0001;
const int MOD_CONTROL = 0x0002;
const int MOD_SHIFT = 0x0004;
const int HOTKEY_ID = 0x1234;
//
// HotKeyのイベントを示すメッセージID
//
const int WM_HOTKEY = 0x0312;
///
/// ホットキーを登録
///
/// <param name="sender" />
/// <param name="e" />
private void button5_Click(object sender, EventArgs e)
{
    if (RegisterHotKey(this.Handle, HOTKEY_ID,  MOD_CONTROL, (int)Keys.PrintScreen) == 0)
    {
        MessageBox.Show("既に他のアプリで使用されています。");
    }
}
///
/// ホットキーを解除
///
/// <param name="sender" />
/// <param name="e" />
private void button6_Click(object sender, EventArgs e)
{
    UnregisterHotKey(this.Handle, HOTKEY_ID);
}
///
/// Window Proc のオーバーライド
///
/// <param name="message" />
protected override void WndProc(ref Message message)
{
    if (message.Msg == WM_HOTKEY && (int)message.WParam == HOTKEY_ID)
    {
        Bitmap bmp = ActiveWindowCapture();
        // bmp.Save(@"c:\work\bmp\" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".bmp");
        // クリップボードへコピー
        Clipboard.SetImage(bmp);
        return;
    }
    base.WndProc(ref message);
}

■参考先

画面をキャプチャする: .NET Tips: C#, VB.NET, Visual Studio
http://dobon.net/vb/dotnet/graphics/screencapture.html
ホットキー(HotKey)の設定 (DllImport, InteropServices, RegisterHotKey, UnRegisterHotKey) – いろいろ備忘録日記
http://d.hatena.ne.jp/gsf_zero1/20070416/p1

カテゴリー: 開発, C# パーマリンク

Ctrl+PrintScreen でアクティブなウィンドウをキャプチャする への6件のフィードバック

  1. 視野箱 のコメント:

    キーボードでメニューを開き(【Alt】+Fなど)その後【Alt】を押しっぱなしの状態でPrintScreenをすればキャプチャできます。
    コンテキストメニューは難しいです。
    【Alt】を押しっぱなしにしていると、右クリックしてもメニューが出てきません。
    【Alt】+【Ctrl】+右クリックなどとすると、メニューが表示できます。これでキャプチャできます。
    ただし、キーボードとの組み合わせによりメニューが異なる場合などは使えません。

  2. masuda のコメント:

    > キーボードでメニューを開き(【Alt】+Fなど)その後【Alt】を押しっぱなしの状態でPrintScreenをすればキャプチャできます。

    おッ、なるほど、これだといけますね。情報 Thanx です。
    Excel 2010 のリボンで使えるかどうか、後で試して見ます。

  3. 視野箱 のコメント:

    Excel2007ですが、リボンは微妙な動きをしますね。
    単純にキーボードでやると、キーボードのヒントが出てしまいます。
    しかも、ドロップダウンを開いた状態でPrintScreenをすると、なんとメニューだけキャプチャされます。
    別ウィンドウということらしいです。
    マウスでやる場合は【Alt】+【Ctrl】+クリックでドロップダウンが開けますが、こちらもメニューだけキャプチャされるようです。

  4. masuda のコメント:

    あ~、そもそも win api を使った方法でキャプチャをすると、右クリックメニュー部分がキャプチャできていないという現象が。
    Windows XP だと ok なのに、Windows 7 だとダメでした。

    用途に足りてないので、あとで方法を考え直しますか。

  5. masuda のコメント:

    IE9 のメニューだとキャプチャできるけど、Visual Studio 2010 のメニューだとキャプチャできないという…謎。

    • masuda のコメント:

      おそらく、ActiveWindow の DC でキャプチャしているので、メニューが消えてしまっている。なので、Desktop の DC を使って、ActiveWinodow の分を切り取れば OK かなぁ。後で試してみる。

コメントは停止中です。