DisplayPortディスプレイには妖精が住んでいる(Windowsのディスプレイ構成をプロファイルごとに切り替える)

以前からWindowsのディスプレイ周りには困惑していて、特にDisplayPort(以下DP)が絡んだ場合には、DPの電源オフ時にはデバイス自体がOS上でオフ扱いになるという仕様からほんとにもうどうしようもない挙動をします。ディスプレイがオフ扱いになる、あるいは復帰するタイミング、またはデフォルトのモニター解像度の存在などが渾然一体となり、休憩から帰った後にウィンドウが元の位置にあることは決して保証されません。そのサイズすらもです。

この問題の対処法はいろいろあります。とりあえず簡単に紹介します。

DPディスプレイの電源を切らずに運用する

シンプルに因果律から導き出されるアイディアです。しばらく放っておくとDPディスプレイはスタンバイ状態に入り、この状態への移行、この状態からの復帰では特に問題は発生しません。 この解決策は良さそうに見えますが、席を立った後、あなたのディスプレイがまだ光を放っていることに気づいた親切な同僚の存在について考察してみましょう。

プログラムから即座にディスプレイをスタンバイ状態に移行する方法を以下に紹介します。あなたのディスプレイのインジケーターがスリープ時にモンスターたちを惹きつけないことを祈ります。

gist9167e2b52ab8033414fd70357079070e

モニターの解像度に関するレジストリ値を変更する

モニターを省電力から復帰させると解像度やウィンドウのサイズが小さくなるのを解決する : プログ 塵の雨日記: DisplayPort接続時のディスプレイのオンオフによるウィンドウの再配置について PC用4Kモニタでウインドウが小さく左上に偏る問題をレジストリ編集で解決

多くの方の直った!という声が寄せられていますが、この方法はマルチディスプレイ環境でウィンドウが別ウインドウに移動してしまう問題については効果がありません。

DPケーブルをハックする

DisplayPortの切断を回避するアダプター - Qiita DisplayPort接続でモニターの電源を切ると認識が外れるのを何とかできる? - Aquablews_apps.dump()

私はこの方法を試していませんが、コストと互換性問題について納得できれば試す価値はあるでしょう。

ウィンドウ位置を管理するツールを使う

あるディスプレイにウィンドウを集めるもの、ウィンドウの状態を保存・復元するものなどいろいろありますが、多くのツールが、異なるDPIを含むマルチディスプレイ環境で正常に動かず、ひとまず断念しました。いいツールがあったら教えてください。

ディスプレイ構成をプロファイルごとに切り替える

試行錯誤の後、最終的にこの方法にたどり着きました。要するに、悪いDPディスプレイは能動的に取り外して、DPディスプレイがオフ扱いになるタイミングを制御しようというものです。前述のレジストリ値を使う方法と組み合わせて、この問題を多少改善することができます。

1. Display Changer IIでWindowsのディスプレイ構成を保存・復元する

Display Changer II « 12noon

例えば以下のコマンドでProfile1.xmlにディスプレイの設定を保存し、復元することができます。

dc2.exe -create="Profile1.xml"
dc2.exe -configure="Profile1.xml"

このxmlファイルはその時点でのWindowsのディスプレイの設定を保存したものなので、グラフィックドライバの更新などでデバイス名などに大きな変更が加わった場合はその都度作り直す必要があります。

2. コマンドをタスクとして登録する

dc2.exe -configure="Profile1.xml" のようなコマンドを管理者権限のタスクとして、タスクスケジューラに登録しておきます。こうすることで、通常権限のAutoHotKeyアプリケーションからコマンドを実行できます。 ここでは例として、SwitchDisplayProfile1, SwitchDisplayProfile2, SwitchDisplayProfile3の3つのプロファイルを作成しました。

3. AutoHotKeyからディスプレイのプロファイルを切り替える

AutoHotKeyスクリプトには前述のDisplayStandBy.exeと管理者権限タスクSwitchDisplayProfile1, SwitchDisplayProfile2, SwitchDisplayProfile3を起動するフック、Ctrl+Shift+Alt+F9, Ctrl+Shift+Alt+F10, Ctrl+Shift+Alt+F11, Ctrl+Shift+Alt+F12を記述しました。

gist869012765c79d16d2604292c890c5f54