キモオタクの部屋

終わりかけの大学生のブログ。不定期に更新します。

【C#】真四角なクライアント領域のスクリーンショットを取る【.NET Framework】

お久しぶりです。キモオタクです。

なぜか僕が今触っている、古代兵器こと.NET framework 4.7.2のネタです。情報がぜんぜん出てこなくて実装に苦労したので、備忘録としてブログに書いておこうと思い筆を執りました。

御託はいいのでコードを見せろという方向け

github.com ウィンドウハンドルを引数に設定すると、クライアント領域をスクショしたBitmapを返します。

状況説明

ウィンドウのクライアント領域をピッタリに切り抜きたい。obsにできるんだから俺にもできるはず。

ぶつかっている問題

  1. windows11は、ウィンドウの角が丸まっている
  2. PrintWindowが正常に映らない
  3. クライアント領域のスクリーン座標が取得できない

これらの要素が有機的に絡まり合って大変なことになっています。一個ずつ解決していきます。

1. ウィンドウの角が丸い問題

windows10はウィンドウが真四角でしたが、11では角が丸くなっています。そのため普通にスクリーンショットを取得しようとすると、角が欠損した画像を入手するハメになります。

対策としてはPrintWindowでAero(死語)を無効化したウィンドウ画像をキャプチャすることでなんとかなります。化石みたいな機能ですが僕は他に方法を思いつきませんでした。

2. PrintWindowが正常に動作しないが

winformsや古いソフトをキャプチャするのはできても、chromeやゲームなどをキャプチャすると出力画像が真っ白 or 真っ黒になってしまいます。対策としては、PrintWindowのnFlagsの値を2にすることで完全に解決します。(ここの解決に一番時間がかかりました…具体的には1年ぐらい…)

参考: stackoverflow.com

3. クライアント座標ってどうやって取得するんや

GetClientRectとClientToScreenとGetWindowRectを組み合わせたらいけます。詳しくは最初に貼ったリポジトリを見るとわかると思います。

おわり

いかがでしたか?参考になった方がいれば幸いです。コメントでの文句やダメ出しをお待ちしております。マジで。