関連ウィンドウもまとめてスクショできるようにしたPixcren、キャプチャ範囲はこれで完成
Pixcren1.2.4
ダウンロード先
ここのPixcren1.2.4zip
github.com
作成動作環境
- Windows 10 Home バージョン 2004
- Visual Studio Community 2019
- WPF
- C#
- .NET 5
動作に必要なのは.NET 5がインストール済みのWindows
規定ファイル名を変更した
ファイル名の日時の書式を空白にしたときの書式を
yyyyMMdd_hh_mm_ss_fff
から
yyyyMMdd_hhmmss_fff
にした
関連ウィンドウをまとめてスクショできるようにした
キャプチャ範囲、ウィンドウ特殊1+
キャプチャ範囲の選択でウィンドウ特殊1+を追加した
ウィンドウ特殊1+でスクショしてみる
デスクトップ画面がこの状態のとき
エクセルのセルの書式で塗りつぶし→塗りつぶし効果→グラデーションの色1→その他の色→色の設定を開いたところ
この状態でスクショすると
この画像が得られる
プレビューウィンドウではこうなっている
ウィンドウ枠外に伸びたリストウィンドウとか
デスクトップ画面
これをウィンドウ特殊1+でスクショすると↓
マウスカーソルが枠外に伸びたリストウィンドウの上にあれば、途切れずにスクショできる。これはキャプチャ範囲のウィンドウ特殊1と同じ効果によるもの、それに加えて+1では関連ウィンドウもキャプチャする、ここでの関連ウィンドウはオプションウィンドウを開いたもとのVisual Studioのウィンドウになる
別のキャプチャ範囲でスクショ
ウィンドウ特殊1
ウィンドウ
大抵のスクショアプリだとこうなる
ウィンドウのクライアント領域
カーソル下のコントロール
関連ウィンドウのハンドル取得方法は
WinAPIのGetWindowでOwnerを使った、なので元のウィンドウのオーナーを辿っているだけ
リボンメニュー系アプリはGetForegroundWindowからGetParentからGetWindowのOwner
それ以外のアプリはGetForegroundWindowからのGetWindowのOwner
仕様という名の不具合
一時停止して配列の中を見ているところ、この状態でのスクショ結果は
こうなってしまう、肝心なVisual Studioのウィンドウがキャプチャできていない
キャプチャ範囲はウィンドウ、ウィンドウ特殊1、ウィンドウ特殊1+でも、ほとんど同じで期待通りにならない
処理の途中を見てみると
cursorが基点になるウィンドウハンドルで、マウスカーソル下のウィンドウ
foreがGetForegroundWindowで取得したウィンドウハンドル、通常は最前面ウィンドウ
これを見るとforeはカーソル下ウィンドウの1階層下のウィンドウになっている。通常ならここでアプリのウィンドウが取得されるから、この場合はVisual Studioのウィンドウが取得されるはずなんだけどねえ
じゃあどうしたらVisual Studioのウィンドウが取得できるのかなって、試しているのがその下に並ぶ変数
cParent {IntPtr(0000000000000000), Rect(0,0,0,0), 不可視, Text()}
cOwner {IntPtr(0000000000000000), Rect(0,0,0,0), 不可視, Text()}
cRoot {IntPtr(00000000001e293a), Rect(1105,623,198,116), 可視, Text()}
act {IntPtr(0000000000000000), Rect(0,0,0,0), 不可視, Text()}
上から順番にパレント、オーナー、ルートオーナー、アクティブウィンドウ
カーソル下ウィンドウを基点にこれだけ試したけど、どれもVisual Studioのウィンドウは取得できず
さらにGetForegroundWindowを基点にしても取得できなかった
ってことでお手上げ、仕様にしよう
こうなってしまう条件は、ブレークポイントで一時停止中に、コードの上にマウスカーソルを乗せると出てくるポップアップウィンドウの中に、虫眼鏡アイコンがあって、その横の▼をクリックしてドロップダウンリストを表示しているとき、かな、他にもあるかもしれないけどかなり限定的だと思う
ここまではいいけど、▼からのドロップダウンリスト表示してしまうと
こうなってしまう
他のスクショアプリもいくつか試したけど、まともに撮れるものはなかったから、かなり特殊なウィンドウみたいねえ
完走した感想
今回で考えていたキャプチャ範囲は全部できた
難しかったのはアプリのウィンドウ枠外に伸びたメニューウィンドウや、右クリックメニューのキャプチャ
普通系アプリの右クリックメニューウィンドウを取得するWinAPIは見つけられなかったので、スクショするときはマウスカーソルをメニューウィンドウに乗せている前提にして、マウスカーソル下のウィンドウを取得するWinAPIで対処
エクセルの同時に2枚出てくる右クリックメニューは無理かなあと思っていたけど、指定ウィンドウの1階層下のウィンドウを取得するGetWindow+NEXTを繰り返して下層ウィンドウを集めて、その中からGetForegroundWindowのルートオーナーと同じルートオーナーを持つウィンドウを選別するという強引な方法と、ドロップシャドウ専用のウィンドウをサイズで判断するとかでなんとかできて、このときは嬉しかった
キャプチャ範囲に関しては予想よりも良くできたので、これで完成!
あとは、プレビューウィンドウをもっとプレビューっぽい動作にしたいのと、画像サイズを縮小して保存できるようにしたい
関連記事
次回は4日後
前回のWPF記事は昨日
最初のPixcrenは50日前
gogowaten.hatenablog.com