作ったアプリ自慢! Advent Calendar 2016 22日目の記事です。
堂々と自慢できるような代物ではないですが、一応最低限の実用には耐える物にはなったと思います。
これまでの既存のキャプチャツールが高解像度モニタ上だとうまく動かないことが多い
昔から定番ツールとしていろんな画面キャプチャツールが出回っていましたが、ここ数年で Windows にエアロシステムが導入されたり高解像度モニタが出回ったりした等の事情により、なんだか既存のキャプチャツールがうまく動かない(キャプチャ位置が完全にズレてしまったり、微妙な隙間ができてしまったり等の)現象が目立つようになってきました。
僕が昔愛用していた Capture STAFF - Light も例に漏れず挙動がどうもおかしいです。
自分の場合は今使ってるマシンが X1 Yoga でディスプレイ解像度が 2560 x 1440 であり普通に使ってると文字が小さすぎて読みにくいため、ディスプレイ設定で全体を 1.5 倍に拡大して作業しています。
そのような(昔では考えられなかったような)環境下で Capture STAFF - Light でキャプチャを行うと、
本来はこうなって欲しいところが
こんな感じにキャプチャ位置がずれたりしていました。
結局自分でキャプチャツールを作り直してみた
「Capture STAFF - Light」の作者さんに伝えて対応いただくことも考えましたが、まず高解像度モニタが検証環境として必要なことと、割と簡単には対応できなそうなやっかいな問題が絡んでそうな気がして、こんな(まだまだ希少な)事例であんまり作者さんに負担かけたくないなーと思い、先に自分で技術検証してみることにしました。
そしてできあがったのがこれです。
ショートカットキーは「Capture STAFF - Light」と同じ Ctrl + F2 を採用しました。
※「Capture STAFF - Light」では今回の WinRealCapture よりもずっと豊富な機能が提供されていたのですが、今回はその一部の機能だけを再現するような形のアプリになっています。
技術抜粋
全ソースはリポジトリ側を見ていただきたいのですが、いくつか主要なポイントをピックアップしておきます。
※かなり突貫で作ったのでソース汚くてアレですがそのうちリファクタします。
高解像度の縮小無効処理
if (Environment.OSVersion.Version.Major >= 6) Win32Wrap.SetProcessDPIAware(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
ウィンドウの位置・サイズ取得部分
// get the size Win32Wrap.RECT windowRect = new Win32Wrap.RECT(); Win32Wrap.GetWindowRect(handle, ref windowRect); int width = windowRect.right - windowRect.left; int height = windowRect.bottom - windowRect.top; // real rect Win32Wrap.RECT windowRect2 = new Win32Wrap.RECT(); Win32Wrap.DwmGetWindowAttribute(handle, Win32Wrap.DWMWA_EXTENDED_FRAME_BOUNDS, ref windowRect2, 4 * 4); int width2 = windowRect2.right - windowRect2.left; int height2 = windowRect2.bottom - windowRect2.top; windowRect = windowRect2; width = width2; height = height2;