手順書などを作るために画面のキャプチャをする時に、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
キーボードでメニューを開き(【Alt】+Fなど)その後【Alt】を押しっぱなしの状態でPrintScreenをすればキャプチャできます。
コンテキストメニューは難しいです。
【Alt】を押しっぱなしにしていると、右クリックしてもメニューが出てきません。
【Alt】+【Ctrl】+右クリックなどとすると、メニューが表示できます。これでキャプチャできます。
ただし、キーボードとの組み合わせによりメニューが異なる場合などは使えません。
> キーボードでメニューを開き(【Alt】+Fなど)その後【Alt】を押しっぱなしの状態でPrintScreenをすればキャプチャできます。
おッ、なるほど、これだといけますね。情報 Thanx です。
Excel 2010 のリボンで使えるかどうか、後で試して見ます。
Excel2007ですが、リボンは微妙な動きをしますね。
単純にキーボードでやると、キーボードのヒントが出てしまいます。
しかも、ドロップダウンを開いた状態でPrintScreenをすると、なんとメニューだけキャプチャされます。
別ウィンドウということらしいです。
マウスでやる場合は【Alt】+【Ctrl】+クリックでドロップダウンが開けますが、こちらもメニューだけキャプチャされるようです。
あ~、そもそも win api を使った方法でキャプチャをすると、右クリックメニュー部分がキャプチャできていないという現象が。
Windows XP だと ok なのに、Windows 7 だとダメでした。
用途に足りてないので、あとで方法を考え直しますか。
IE9 のメニューだとキャプチャできるけど、Visual Studio 2010 のメニューだとキャプチャできないという…謎。
おそらく、ActiveWindow の DC でキャプチャしているので、メニューが消えてしまっている。なので、Desktop の DC を使って、ActiveWinodow の分を切り取れば OK かなぁ。後で試してみる。