【コピペで簡単】C#でスクリーン(画面) キャプチャするには(マルチモニタ対応)

当ページのリンクには広告が含まれています。

C#でスクリーン(画面)キャプチャする方法は、Windows標準機能からフリーソフトまで数多く出回っています。

しかし、実際に使ってみると、自分が求める使い方が出来ない、もうすこしこんな機能が欲しいなど、なかなかピッタリとニーズが合うものが見つかりません。

そこで、オリジナルの画面キャプチャアプリを作ることにしたのですが、その時に調べた内容をご紹介したいと思います。

コピペで簡単に使えるようにクラス化してみたので、とりあえずC#からキャプチャが撮りたいという方は、是非コピペしてお使いください。

ちなみに、WindowsForm、WPF共通です。

目次

キャプチャの方法

スクリーンキャプチャを行う手順は次の通りです。

  • キャプチャイメージを格納するBitmapを作成
  • 作成したBitmapを引数としてGraphicsオブジェクトを作成
  • CopyFromScreen で Bitmap にキャプチャイメージを格納

画面の指定区画をキャプチャする

以上の事を踏まえて指定した区画のキャプチャ画像を返してくれるサンプルを作ってみました。

引数に区画の座標(X1,Y1,X2,Y2)を渡すと、その範囲のキャプチャ画像をBitmap として返してくれます。

CopyFromScreenの引数は、左から 始点X、始点Y、転送先のオフセットX、転送先のオフセットY、区画のサイズを指定します。

スクリーン(画面)全体をキャプチャする

画面全体をキャプチャしたい場合、 WindowsFromの場合は System.Windows.Forms.Screen を、WPFの場合は SystemParameters を参照することでで、スクリーンの縦と横のサイズを取得できますので、これを CopyFromScreen に渡します。

WindowsFormの場合Screen.PrimaryScreen.Bounds.Width
Screen.PrimaryScreen.Bounds.Height
WPFの場合SystemParameters.FullPrimaryScreenWidth
SystemParameters.FullPrimaryScreenHeight

先ほど紹介した Capture 関数を使うのであれば、以下の様に記述可能です。

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

アクティブウィンドウをキャプチャする場合、アクティブウィンドウの座標とサイズを取得する必要がありますが、これは .NET 標準では用意されていません。

そのため、User32.DLL と dwmapi.dell をインポートして、直接WindowsのAPIを呼び出すことになります。

そして、実際にアクティブウィンドウの座標を取得するには、次のようになります。

GetForegroundWindow()でアクティブウィンドウのハンドルを取得し、DwmGetWindowAttributeで座標を取得しています。

DWMWA_EXTENDED_FRAME_BOUNDS はウィンドウの境界情報を取得するための定数で、WindowRectは、Windows API から座標を受け取るための構造体ですが、詳細はサンプルソースに記載しているので、そちらをご確認下さい。

マルチモニタでのキャプチャ

パソコンに接続されているモニタの情報は、System.Windows.Forms.Screen で取得可能です。

一方、WPFの場合は残念ながら接続されているスクリーン情報を取得する方法がありません。

したがって、WPFでも System.Windows.Forms.Screen を使う必要があります。

画面の指定区画をキャプチャする

マルチモニタの場合、あたかも1つの巨大なモニタのように扱われます。

下記は3台のモニタが接続されている例ですが、真ん中のモニタの左上座標げ(0,0) となっており、左側はマイナス座標(-1980,0)が割り当てられます。

Windowsのディスプレイ設定において、プライマリ座標が(0,0)となり、これより左はマイナス、右はプラスの座標が割り当てられます。

例えば、1がプライマリ、2がサブモニタだった場合、プライマリより左側に設置されたモニタの(0,0)~(100,100) の区間をキャプチャしたい場合、次の様に記述します。

指定したスクリーン(画面)全体をキャプチャする

パソコンに接続されているモニタは、System.Windows.Forms.Screen に実装されている AllScreens プロパティで取得できます。

この配列からキャプチャしたいモニタを指定し、Bounds.Height,Bouns.Width を取得すれば、任意のモニタの画面全体がキャプチャ可能です。

下記は、配列0番目のスクリーンに対して、画面全体をキャプチャするサンプルです。

ちなみに、Primary メソッドを参照することで、どれがプライマリなのかを知ることができます。

プライマリの場合は true 、そうでない場合は false になっています。

すべてのスクリーン全体をキャプチャする

System.Windows.Forms.Screen.AllScreens を使って全てのスクリーンの座標を取得し、そこから左上(最小座標)と右下(最大座標)を求めることで、1枚の画像にキャプチャできます。

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

アクティブウィンドウに関しては、マルチモニタのどこに表示されていても関係ありません。

プライマリと全く同じで、次の記述でキャプチャできます。

サンプルソース(クラス化したもの)

これまでの内容を元に、キャプチャを簡単に行えるようクラス化したサンプルソースは次のようになります。

使い方はコメントを見ていただくと分かると思うので割愛します。

ファイルに保存するには

参考までに、キャプチャしたイメージ(Bitmap)をファイルに保存するサンプルを紹介しておきます。

単独で使って頂いても結構ですし、上記のクラスに入れてご利用いただいても結構です。

BitmapクラスのSaveメソッドを使って保存していますが、そのままではJPGの画質が荒いので、引数の quality で画質を調整(100が最高)できるようにしています。

まとめ

今回は、C#でスクリーン(画面)キャプチャする方法について、具体的なサンプルプログラムを用いて解説致しました。

マルチモニタの場合であっても、プログラムから扱う場合は1つの巨大なモニタが接続されているイメージで扱えます。

プライマリより左側のモニタはX軸がマイナスになりますが、そのポイントさえ押さえておけば、マルチモニタ構成であっても任意の範囲をキャプチャすることができます。

画面キャプチャのフリーソフトは数多く出回っていますが、もし自分のニーズに合わずに自作を考えた場合、是非この記事を参考にしてください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次